mirror of
https://github.com/postgres/postgres.git
synced 2025-04-21 12:05:57 +03:00
Default values for function arguments
Pavel Stehule, with some tweaks by Peter Eisentraut
This commit is contained in:
parent
7b640b0345
commit
455dffbb73
@ -1,4 +1,4 @@
|
|||||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.460 2008/11/14 00:51:46 tgl Exp $ -->
|
<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.461 2008/12/04 17:51:26 petere Exp $ -->
|
||||||
|
|
||||||
<chapter id="functions">
|
<chapter id="functions">
|
||||||
<title>Functions and Operators</title>
|
<title>Functions and Operators</title>
|
||||||
@ -11710,6 +11710,10 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
|
|||||||
<primary>pg_get_function_arguments</primary>
|
<primary>pg_get_function_arguments</primary>
|
||||||
</indexterm>
|
</indexterm>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>pg_get_function_identity_arguments</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
<indexterm>
|
<indexterm>
|
||||||
<primary>pg_get_function_result</primary>
|
<primary>pg_get_function_result</primary>
|
||||||
</indexterm>
|
</indexterm>
|
||||||
@ -11799,7 +11803,12 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
|
|||||||
<row>
|
<row>
|
||||||
<entry><literal><function>pg_get_function_arguments</function>(<parameter>func_oid</parameter>)</literal></entry>
|
<entry><literal><function>pg_get_function_arguments</function>(<parameter>func_oid</parameter>)</literal></entry>
|
||||||
<entry><type>text</type></entry>
|
<entry><type>text</type></entry>
|
||||||
<entry>get argument list for function</entry>
|
<entry>get argument list of function's definition (with default values)</entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry><literal><function>pg_get_function_identity_arguments</function>(<parameter>func_oid</parameter>)</literal></entry>
|
||||||
|
<entry><type>text</type></entry>
|
||||||
|
<entry>get argument list to identify a function (without argument names, default values)</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry><literal><function>pg_get_function_result</function>(<parameter>func_oid</parameter>)</literal></entry>
|
<entry><literal><function>pg_get_function_result</function>(<parameter>func_oid</parameter>)</literal></entry>
|
||||||
@ -11921,6 +11930,11 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
|
|||||||
<command>CREATE FUNCTION</>.
|
<command>CREATE FUNCTION</>.
|
||||||
<function>pg_get_function_result</function> similarly returns the
|
<function>pg_get_function_result</function> similarly returns the
|
||||||
appropriate <literal>RETURNS</> clause for the function.
|
appropriate <literal>RETURNS</> clause for the function.
|
||||||
|
<function>pg_get_function_identity_arguments</function> returns the
|
||||||
|
argument list necessary to identify a function, in the form it
|
||||||
|
would need to appear in within <command>ALTER FUNCTION</>, for
|
||||||
|
instance. This form omits default values and argument names, for
|
||||||
|
example.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$PostgreSQL: pgsql/doc/src/sgml/ref/create_function.sgml,v 1.81 2008/11/14 10:22:46 petere Exp $
|
$PostgreSQL: pgsql/doc/src/sgml/ref/create_function.sgml,v 1.82 2008/12/04 17:51:26 petere Exp $
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<refentry id="SQL-CREATEFUNCTION">
|
<refentry id="SQL-CREATEFUNCTION">
|
||||||
@ -21,7 +21,7 @@ $PostgreSQL: pgsql/doc/src/sgml/ref/create_function.sgml,v 1.81 2008/11/14 10:22
|
|||||||
<refsynopsisdiv>
|
<refsynopsisdiv>
|
||||||
<synopsis>
|
<synopsis>
|
||||||
CREATE [ OR REPLACE ] FUNCTION
|
CREATE [ OR REPLACE ] FUNCTION
|
||||||
<replaceable class="parameter">name</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] )
|
<replaceable class="parameter">name</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [ { DEFAULT | = } <replaceable class="parameter">defexpr</replaceable>] [, ...] ] )
|
||||||
[ RETURNS <replaceable class="parameter">rettype</replaceable>
|
[ RETURNS <replaceable class="parameter">rettype</replaceable>
|
||||||
| RETURNS TABLE ( <replaceable class="parameter">colname</replaceable> <replaceable class="parameter">coltype</replaceable> [, ...] ) ]
|
| RETURNS TABLE ( <replaceable class="parameter">colname</replaceable> <replaceable class="parameter">coltype</replaceable> [, ...] ) ]
|
||||||
{ LANGUAGE <replaceable class="parameter">langname</replaceable>
|
{ LANGUAGE <replaceable class="parameter">langname</replaceable>
|
||||||
@ -154,6 +154,20 @@ CREATE [ OR REPLACE ] FUNCTION
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><replaceable class="parameter">defexpr</replaceable></term>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
An expression to be used as default value if the parameter is
|
||||||
|
not specified. The expression has to be convertable to the
|
||||||
|
argument type of the parameter. All parameters after a
|
||||||
|
parameter with default value have to be parameters with default
|
||||||
|
values as well.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><replaceable class="parameter">rettype</replaceable></term>
|
<term><replaceable class="parameter">rettype</replaceable></term>
|
||||||
|
|
||||||
@ -667,6 +681,14 @@ COMMIT;
|
|||||||
either before or after <replaceable class="parameter">argname</replaceable>.
|
either before or after <replaceable class="parameter">argname</replaceable>.
|
||||||
But only the first way is standard-compliant.
|
But only the first way is standard-compliant.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The SQL standard does not specify parameter defaults. The syntax
|
||||||
|
with the <literal>DEFAULT</literal> key word is from Oracle, and it
|
||||||
|
is somewhat in the spirit of the standard: SQL/PSM uses it for
|
||||||
|
variable default values. The syntax with <literal>=</literal> is
|
||||||
|
used in T-SQL and Firebird.
|
||||||
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/xfunc.sgml,v 1.133 2008/10/31 19:37:56 tgl Exp $ -->
|
<!-- $PostgreSQL: pgsql/doc/src/sgml/xfunc.sgml,v 1.134 2008/12/04 17:51:26 petere Exp $ -->
|
||||||
|
|
||||||
<sect1 id="xfunc">
|
<sect1 id="xfunc">
|
||||||
<title>User-Defined Functions</title>
|
<title>User-Defined Functions</title>
|
||||||
@ -663,6 +663,60 @@ SELECT mleast(VARIADIC ARRAY[10, -1, 5, 4.4]);
|
|||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="xfunc-parameter-defaults">
|
||||||
|
<title><acronym>SQL</> Functions with Parameters Default Values</title>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>default values</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Functions can be declared with parameters with default values or
|
||||||
|
expressions. The default expressions are used as parameter value
|
||||||
|
if the parameter is not explicitly specified in a function call.
|
||||||
|
All parameters after a a parameter with default value have to be
|
||||||
|
parameters with default values as well.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
For example:
|
||||||
|
<screen>
|
||||||
|
CREATE FUNCTION foo(a int DEFAULT 1, b int DEFAULT 2, c int DEFAULT 3)
|
||||||
|
RETURNS int
|
||||||
|
LANGUAGE SQL
|
||||||
|
AS $$
|
||||||
|
SELECT $1 + $2 + $3;
|
||||||
|
$$;
|
||||||
|
|
||||||
|
SELECT foo(10, 20, 30);
|
||||||
|
foo
|
||||||
|
-----
|
||||||
|
60
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT foo(10, 20);
|
||||||
|
foo
|
||||||
|
-----
|
||||||
|
33
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT foo(10);
|
||||||
|
foo
|
||||||
|
-----
|
||||||
|
15
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT foo();
|
||||||
|
foo
|
||||||
|
-----
|
||||||
|
6
|
||||||
|
(1 row)
|
||||||
|
</screen>
|
||||||
|
Instead of the key word <literal>DEFAULT</literal>,
|
||||||
|
the <literal>=</literal> sign can also be used.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
<sect2 id="xfunc-sql-table-functions">
|
<sect2 id="xfunc-sql-table-functions">
|
||||||
<title><acronym>SQL</acronym> Functions as Table Sources</title>
|
<title><acronym>SQL</acronym> Functions as Table Sources</title>
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.112 2008/09/09 18:58:08 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.113 2008/12/04 17:51:26 petere Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -571,6 +571,11 @@ TypeIsVisible(Oid typid)
|
|||||||
* If expand_variadic is false, variadic arguments are not treated specially,
|
* If expand_variadic is false, variadic arguments are not treated specially,
|
||||||
* and the returned nvargs will always be zero.
|
* and the returned nvargs will always be zero.
|
||||||
*
|
*
|
||||||
|
* If expand_variadic is true, functions with argument default values
|
||||||
|
* will also be retrieved. If expand_variadic is false, default
|
||||||
|
* values will not be taken into account and functions that do not
|
||||||
|
* have exactly nargs arguments in total will not be considered.
|
||||||
|
*
|
||||||
* We search a single namespace if the function name is qualified, else
|
* We search a single namespace if the function name is qualified, else
|
||||||
* all namespaces in the search path. The return list will never contain
|
* all namespaces in the search path. The return list will never contain
|
||||||
* multiple entries with identical argument lists --- in the multiple-
|
* multiple entries with identical argument lists --- in the multiple-
|
||||||
@ -621,13 +626,45 @@ FuncnameGetCandidates(List *names, int nargs, bool expand_variadic)
|
|||||||
int pathpos = 0;
|
int pathpos = 0;
|
||||||
bool variadic;
|
bool variadic;
|
||||||
Oid va_elem_type;
|
Oid va_elem_type;
|
||||||
|
List *defaults = NIL;
|
||||||
FuncCandidateList newResult;
|
FuncCandidateList newResult;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if function has some parameter defaults if some
|
||||||
|
* parameters are missing.
|
||||||
|
*/
|
||||||
|
if (pronargs > nargs && expand_variadic)
|
||||||
|
{
|
||||||
|
bool isnull;
|
||||||
|
Datum proargdefaults;
|
||||||
|
char *str;
|
||||||
|
|
||||||
|
/* skip when not enough default expressions */
|
||||||
|
if (nargs + procform->pronargdefaults < pronargs)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
proargdefaults = SysCacheGetAttr(PROCOID, proctup,
|
||||||
|
Anum_pg_proc_proargdefaults, &isnull);
|
||||||
|
Assert(!isnull);
|
||||||
|
str = TextDatumGetCString(proargdefaults);
|
||||||
|
defaults = (List *) stringToNode(str);
|
||||||
|
|
||||||
|
Assert(IsA(defaults, List));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we don't have to use all default parameters, we skip
|
||||||
|
* some cells from the left.
|
||||||
|
*/
|
||||||
|
defaults = list_copy_tail(defaults, procform->pronargdefaults - pronargs + nargs);
|
||||||
|
|
||||||
|
pfree(str);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if function is variadic, and get variadic element type if so.
|
* Check if function is variadic, and get variadic element type if so.
|
||||||
* If expand_variadic is false, we should just ignore variadic-ness.
|
* If expand_variadic is false, we should just ignore variadic-ness.
|
||||||
*/
|
*/
|
||||||
if (expand_variadic)
|
if (pronargs <= nargs && expand_variadic)
|
||||||
{
|
{
|
||||||
va_elem_type = procform->provariadic;
|
va_elem_type = procform->provariadic;
|
||||||
variadic = OidIsValid(va_elem_type);
|
variadic = OidIsValid(va_elem_type);
|
||||||
@ -638,11 +675,16 @@ FuncnameGetCandidates(List *names, int nargs, bool expand_variadic)
|
|||||||
variadic = false;
|
variadic = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Assert(!variadic || !defaults);
|
||||||
|
|
||||||
/* Ignore if it doesn't match requested argument count */
|
/* Ignore if it doesn't match requested argument count */
|
||||||
if (nargs >= 0 &&
|
if (nargs >= 0 &&
|
||||||
(variadic ? (pronargs > nargs) : (pronargs != nargs)))
|
(variadic ? (pronargs > nargs) : (defaults ? (pronargs < nargs) : (pronargs != nargs))))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
Assert(!variadic || (pronargs <= nargs));
|
||||||
|
Assert(!defaults || (pronargs > nargs));
|
||||||
|
|
||||||
if (OidIsValid(namespaceId))
|
if (OidIsValid(namespaceId))
|
||||||
{
|
{
|
||||||
/* Consider only procs in specified namespace */
|
/* Consider only procs in specified namespace */
|
||||||
@ -681,6 +723,7 @@ FuncnameGetCandidates(List *names, int nargs, bool expand_variadic)
|
|||||||
newResult->pathpos = pathpos;
|
newResult->pathpos = pathpos;
|
||||||
newResult->oid = HeapTupleGetOid(proctup);
|
newResult->oid = HeapTupleGetOid(proctup);
|
||||||
newResult->nargs = effective_nargs;
|
newResult->nargs = effective_nargs;
|
||||||
|
newResult->argdefaults = defaults;
|
||||||
memcpy(newResult->args, procform->proargtypes.values,
|
memcpy(newResult->args, procform->proargtypes.values,
|
||||||
pronargs * sizeof(Oid));
|
pronargs * sizeof(Oid));
|
||||||
if (variadic)
|
if (variadic)
|
||||||
@ -695,6 +738,8 @@ FuncnameGetCandidates(List *names, int nargs, bool expand_variadic)
|
|||||||
else
|
else
|
||||||
newResult->nvargs = 0;
|
newResult->nvargs = 0;
|
||||||
|
|
||||||
|
any_variadic = variadic || defaults;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Does it have the same arguments as something we already accepted?
|
* Does it have the same arguments as something we already accepted?
|
||||||
* If so, decide which one to keep. We can skip this check for the
|
* If so, decide which one to keep. We can skip this check for the
|
||||||
@ -704,6 +749,9 @@ FuncnameGetCandidates(List *names, int nargs, bool expand_variadic)
|
|||||||
*/
|
*/
|
||||||
if (any_variadic || !OidIsValid(namespaceId))
|
if (any_variadic || !OidIsValid(namespaceId))
|
||||||
{
|
{
|
||||||
|
if (defaults)
|
||||||
|
effective_nargs = nargs;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we have an ordered list from SearchSysCacheList (the normal
|
* If we have an ordered list from SearchSysCacheList (the normal
|
||||||
* case), then any conflicting proc must immediately adjoin this
|
* case), then any conflicting proc must immediately adjoin this
|
||||||
@ -733,11 +781,21 @@ FuncnameGetCandidates(List *names, int nargs, bool expand_variadic)
|
|||||||
prevResult;
|
prevResult;
|
||||||
prevResult = prevResult->next)
|
prevResult = prevResult->next)
|
||||||
{
|
{
|
||||||
if (effective_nargs == prevResult->nargs &&
|
if (!defaults)
|
||||||
memcmp(newResult->args,
|
{
|
||||||
prevResult->args,
|
if (effective_nargs == prevResult->nargs &&
|
||||||
effective_nargs * sizeof(Oid)) == 0)
|
memcmp(newResult->args,
|
||||||
|
prevResult->args,
|
||||||
|
effective_nargs * sizeof(Oid)) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (memcmp(newResult->args,
|
||||||
|
prevResult->args,
|
||||||
|
effective_nargs * sizeof(Oid)) == 0)
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (prevResult)
|
if (prevResult)
|
||||||
@ -777,6 +835,20 @@ FuncnameGetCandidates(List *names, int nargs, bool expand_variadic)
|
|||||||
pfree(newResult);
|
pfree(newResult);
|
||||||
continue; /* keep previous result */
|
continue; /* keep previous result */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (defaults)
|
||||||
|
{
|
||||||
|
if (prevResult->argdefaults != NIL)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_AMBIGUOUS_FUNCTION),
|
||||||
|
errmsg("functions with parameter defaults %s and %s are ambiguous",
|
||||||
|
func_signature_string(names, pronargs, procform->proargtypes.values),
|
||||||
|
func_signature_string(names, prevResult->nargs, prevResult->args))));
|
||||||
|
/* else, previous result didn't have defaults */
|
||||||
|
pfree(newResult);
|
||||||
|
continue; /* keep previous result */
|
||||||
|
}
|
||||||
|
|
||||||
/* non-variadic can replace a previous variadic */
|
/* non-variadic can replace a previous variadic */
|
||||||
Assert(prevResult->nvargs > 0);
|
Assert(prevResult->nvargs > 0);
|
||||||
}
|
}
|
||||||
@ -784,6 +856,7 @@ FuncnameGetCandidates(List *names, int nargs, bool expand_variadic)
|
|||||||
prevResult->pathpos = pathpos;
|
prevResult->pathpos = pathpos;
|
||||||
prevResult->oid = newResult->oid;
|
prevResult->oid = newResult->oid;
|
||||||
prevResult->nvargs = newResult->nvargs;
|
prevResult->nvargs = newResult->nvargs;
|
||||||
|
prevResult->argdefaults = newResult->argdefaults;
|
||||||
pfree(newResult);
|
pfree(newResult);
|
||||||
continue; /* args are same, of course */
|
continue; /* args are same, of course */
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/catalog/pg_aggregate.c,v 1.97 2008/11/14 19:47:50 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/catalog/pg_aggregate.c,v 1.98 2008/12/04 17:51:26 petere Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -229,7 +229,8 @@ AggregateCreate(const char *aggName,
|
|||||||
PointerGetDatum(NULL), /* parameterNames */
|
PointerGetDatum(NULL), /* parameterNames */
|
||||||
PointerGetDatum(NULL), /* proconfig */
|
PointerGetDatum(NULL), /* proconfig */
|
||||||
1, /* procost */
|
1, /* procost */
|
||||||
0); /* prorows */
|
0, /* prorows */
|
||||||
|
NULL); /* parameterDefaults */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Okay to create the pg_aggregate entry.
|
* Okay to create the pg_aggregate entry.
|
||||||
@ -321,7 +322,7 @@ lookup_agg_function(List *fnName,
|
|||||||
*/
|
*/
|
||||||
fdresult = func_get_detail(fnName, NIL, nargs, input_types, false,
|
fdresult = func_get_detail(fnName, NIL, nargs, input_types, false,
|
||||||
&fnOid, rettype, &retset, &nvargs,
|
&fnOid, rettype, &retset, &nvargs,
|
||||||
&true_oid_array);
|
&true_oid_array, NULL);
|
||||||
|
|
||||||
/* only valid case is a normal function not returning a set */
|
/* only valid case is a normal function not returning a set */
|
||||||
if (fdresult != FUNCDETAIL_NORMAL || !OidIsValid(fnOid))
|
if (fdresult != FUNCDETAIL_NORMAL || !OidIsValid(fnOid))
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.154 2008/11/02 01:45:27 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.155 2008/12/04 17:51:26 petere Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -75,7 +75,8 @@ ProcedureCreate(const char *procedureName,
|
|||||||
Datum parameterNames,
|
Datum parameterNames,
|
||||||
Datum proconfig,
|
Datum proconfig,
|
||||||
float4 procost,
|
float4 procost,
|
||||||
float4 prorows)
|
float4 prorows,
|
||||||
|
List *parameterDefaults)
|
||||||
{
|
{
|
||||||
Oid retval;
|
Oid retval;
|
||||||
int parameterCount;
|
int parameterCount;
|
||||||
@ -295,6 +296,7 @@ ProcedureCreate(const char *procedureName,
|
|||||||
values[Anum_pg_proc_proretset - 1] = BoolGetDatum(returnsSet);
|
values[Anum_pg_proc_proretset - 1] = BoolGetDatum(returnsSet);
|
||||||
values[Anum_pg_proc_provolatile - 1] = CharGetDatum(volatility);
|
values[Anum_pg_proc_provolatile - 1] = CharGetDatum(volatility);
|
||||||
values[Anum_pg_proc_pronargs - 1] = UInt16GetDatum(parameterCount);
|
values[Anum_pg_proc_pronargs - 1] = UInt16GetDatum(parameterCount);
|
||||||
|
values[Anum_pg_proc_pronargdefaults - 1] = UInt16GetDatum(list_length(parameterDefaults));
|
||||||
values[Anum_pg_proc_prorettype - 1] = ObjectIdGetDatum(returnType);
|
values[Anum_pg_proc_prorettype - 1] = ObjectIdGetDatum(returnType);
|
||||||
values[Anum_pg_proc_proargtypes - 1] = PointerGetDatum(parameterTypes);
|
values[Anum_pg_proc_proargtypes - 1] = PointerGetDatum(parameterTypes);
|
||||||
if (allParameterTypes != PointerGetDatum(NULL))
|
if (allParameterTypes != PointerGetDatum(NULL))
|
||||||
@ -309,6 +311,13 @@ ProcedureCreate(const char *procedureName,
|
|||||||
values[Anum_pg_proc_proargnames - 1] = parameterNames;
|
values[Anum_pg_proc_proargnames - 1] = parameterNames;
|
||||||
else
|
else
|
||||||
nulls[Anum_pg_proc_proargnames - 1] = true;
|
nulls[Anum_pg_proc_proargnames - 1] = true;
|
||||||
|
if (parameterDefaults != PointerGetDatum(NULL))
|
||||||
|
{
|
||||||
|
Assert(list_length(parameterDefaults) > 0);
|
||||||
|
values[Anum_pg_proc_proargdefaults - 1] = CStringGetTextDatum(nodeToString(parameterDefaults));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
nulls[Anum_pg_proc_proargdefaults - 1] = true;
|
||||||
values[Anum_pg_proc_prosrc - 1] = CStringGetTextDatum(prosrc);
|
values[Anum_pg_proc_prosrc - 1] = CStringGetTextDatum(prosrc);
|
||||||
if (probin)
|
if (probin)
|
||||||
values[Anum_pg_proc_probin - 1] = CStringGetTextDatum(probin);
|
values[Anum_pg_proc_probin - 1] = CStringGetTextDatum(probin);
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.101 2008/11/02 01:45:27 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.102 2008/12/04 17:51:26 petere Exp $
|
||||||
*
|
*
|
||||||
* DESCRIPTION
|
* DESCRIPTION
|
||||||
* These routines take the parse tree and pick out the
|
* These routines take the parse tree and pick out the
|
||||||
@ -49,8 +49,10 @@
|
|||||||
#include "commands/proclang.h"
|
#include "commands/proclang.h"
|
||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
#include "parser/parse_coerce.h"
|
#include "parser/parse_coerce.h"
|
||||||
|
#include "parser/parse_expr.h"
|
||||||
#include "parser/parse_func.h"
|
#include "parser/parse_func.h"
|
||||||
#include "parser/parse_type.h"
|
#include "parser/parse_type.h"
|
||||||
|
#include "parser/parse_utilcmd.h"
|
||||||
#include "utils/acl.h"
|
#include "utils/acl.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
#include "utils/fmgroids.h"
|
#include "utils/fmgroids.h"
|
||||||
@ -164,7 +166,9 @@ examine_parameter_list(List *parameters, Oid languageOid,
|
|||||||
ArrayType **allParameterTypes,
|
ArrayType **allParameterTypes,
|
||||||
ArrayType **parameterModes,
|
ArrayType **parameterModes,
|
||||||
ArrayType **parameterNames,
|
ArrayType **parameterNames,
|
||||||
Oid *requiredResultType)
|
List **parameterDefaults,
|
||||||
|
Oid *requiredResultType,
|
||||||
|
const char *queryString)
|
||||||
{
|
{
|
||||||
int parameterCount = list_length(parameters);
|
int parameterCount = list_length(parameters);
|
||||||
Oid *inTypes;
|
Oid *inTypes;
|
||||||
@ -177,6 +181,8 @@ examine_parameter_list(List *parameters, Oid languageOid,
|
|||||||
bool have_names = false;
|
bool have_names = false;
|
||||||
ListCell *x;
|
ListCell *x;
|
||||||
int i;
|
int i;
|
||||||
|
bool have_defaults = false;
|
||||||
|
ParseState *pstate;
|
||||||
|
|
||||||
*requiredResultType = InvalidOid; /* default result */
|
*requiredResultType = InvalidOid; /* default result */
|
||||||
|
|
||||||
@ -184,6 +190,10 @@ examine_parameter_list(List *parameters, Oid languageOid,
|
|||||||
allTypes = (Datum *) palloc(parameterCount * sizeof(Datum));
|
allTypes = (Datum *) palloc(parameterCount * sizeof(Datum));
|
||||||
paramModes = (Datum *) palloc(parameterCount * sizeof(Datum));
|
paramModes = (Datum *) palloc(parameterCount * sizeof(Datum));
|
||||||
paramNames = (Datum *) palloc0(parameterCount * sizeof(Datum));
|
paramNames = (Datum *) palloc0(parameterCount * sizeof(Datum));
|
||||||
|
*parameterDefaults = NIL;
|
||||||
|
|
||||||
|
pstate = make_parsestate(NULL);
|
||||||
|
pstate->p_sourcetext = queryString;
|
||||||
|
|
||||||
/* Scan the list and extract data into work arrays */
|
/* Scan the list and extract data into work arrays */
|
||||||
i = 0;
|
i = 0;
|
||||||
@ -276,9 +286,33 @@ examine_parameter_list(List *parameters, Oid languageOid,
|
|||||||
have_names = true;
|
have_names = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fp->defexpr)
|
||||||
|
{
|
||||||
|
if (fp->mode != FUNC_PARAM_IN && fp->mode != FUNC_PARAM_INOUT)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
|
||||||
|
errmsg("only IN and INOUT parameters can have default values")));
|
||||||
|
|
||||||
|
*parameterDefaults = lappend(*parameterDefaults,
|
||||||
|
coerce_to_specific_type(NULL,
|
||||||
|
transformExpr(pstate, fp->defexpr),
|
||||||
|
toid,
|
||||||
|
"DEFAULT"));
|
||||||
|
have_defaults = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (have_defaults)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
|
||||||
|
errmsg("parameter without default value specified after parameter with default value")));
|
||||||
|
}
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free_parsestate(pstate);
|
||||||
|
|
||||||
/* Now construct the proper outputs as needed */
|
/* Now construct the proper outputs as needed */
|
||||||
*parameterTypes = buildoidvector(inTypes, inCount);
|
*parameterTypes = buildoidvector(inTypes, inCount);
|
||||||
|
|
||||||
@ -653,7 +687,7 @@ interpret_AS_clause(Oid languageOid, const char *languageName,
|
|||||||
* Execute a CREATE FUNCTION utility statement.
|
* Execute a CREATE FUNCTION utility statement.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
CreateFunction(CreateFunctionStmt *stmt)
|
CreateFunction(CreateFunctionStmt *stmt, const char *queryString)
|
||||||
{
|
{
|
||||||
char *probin_str;
|
char *probin_str;
|
||||||
char *prosrc_str;
|
char *prosrc_str;
|
||||||
@ -680,6 +714,7 @@ CreateFunction(CreateFunctionStmt *stmt)
|
|||||||
HeapTuple languageTuple;
|
HeapTuple languageTuple;
|
||||||
Form_pg_language languageStruct;
|
Form_pg_language languageStruct;
|
||||||
List *as_clause;
|
List *as_clause;
|
||||||
|
List *defaults = NULL;
|
||||||
|
|
||||||
/* Convert list of names to a name and namespace */
|
/* Convert list of names to a name and namespace */
|
||||||
namespaceId = QualifiedNameGetCreationNamespace(stmt->funcname,
|
namespaceId = QualifiedNameGetCreationNamespace(stmt->funcname,
|
||||||
@ -753,7 +788,9 @@ CreateFunction(CreateFunctionStmt *stmt)
|
|||||||
&allParameterTypes,
|
&allParameterTypes,
|
||||||
¶meterModes,
|
¶meterModes,
|
||||||
¶meterNames,
|
¶meterNames,
|
||||||
&requiredResultType);
|
&defaults,
|
||||||
|
&requiredResultType,
|
||||||
|
queryString);
|
||||||
|
|
||||||
if (stmt->returnType)
|
if (stmt->returnType)
|
||||||
{
|
{
|
||||||
@ -836,7 +873,8 @@ CreateFunction(CreateFunctionStmt *stmt)
|
|||||||
PointerGetDatum(parameterNames),
|
PointerGetDatum(parameterNames),
|
||||||
PointerGetDatum(proconfig),
|
PointerGetDatum(proconfig),
|
||||||
procost,
|
procost,
|
||||||
prorows);
|
prorows,
|
||||||
|
defaults);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/proclang.c,v 1.80 2008/11/02 01:45:27 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/proclang.c,v 1.81 2008/12/04 17:51:26 petere Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -149,7 +149,8 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
|
|||||||
PointerGetDatum(NULL),
|
PointerGetDatum(NULL),
|
||||||
PointerGetDatum(NULL),
|
PointerGetDatum(NULL),
|
||||||
1,
|
1,
|
||||||
0);
|
0,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -182,7 +183,8 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
|
|||||||
PointerGetDatum(NULL),
|
PointerGetDatum(NULL),
|
||||||
PointerGetDatum(NULL),
|
PointerGetDatum(NULL),
|
||||||
1,
|
1,
|
||||||
0);
|
0,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.414 2008/12/04 11:42:23 heikki Exp $
|
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.415 2008/12/04 17:51:26 petere Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -2448,6 +2448,7 @@ _copyFunctionParameter(FunctionParameter *from)
|
|||||||
COPY_STRING_FIELD(name);
|
COPY_STRING_FIELD(name);
|
||||||
COPY_NODE_FIELD(argType);
|
COPY_NODE_FIELD(argType);
|
||||||
COPY_SCALAR_FIELD(mode);
|
COPY_SCALAR_FIELD(mode);
|
||||||
|
COPY_NODE_FIELD(defexpr);
|
||||||
|
|
||||||
return newnode;
|
return newnode;
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.339 2008/12/04 11:42:24 heikki Exp $
|
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.340 2008/12/04 17:51:26 petere Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1165,6 +1165,7 @@ _equalFunctionParameter(FunctionParameter *a, FunctionParameter *b)
|
|||||||
COMPARE_STRING_FIELD(name);
|
COMPARE_STRING_FIELD(name);
|
||||||
COMPARE_NODE_FIELD(argType);
|
COMPARE_NODE_FIELD(argType);
|
||||||
COMPARE_SCALAR_FIELD(mode);
|
COMPARE_SCALAR_FIELD(mode);
|
||||||
|
COMPARE_NODE_FIELD(defexpr);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* HISTORY
|
||||||
* AUTHOR DATE MAJOR EVENT
|
* AUTHOR DATE MAJOR EVENT
|
||||||
@ -255,6 +255,7 @@ static TypeName *TableFuncTypeName(List *columns);
|
|||||||
%type <list> stmtblock stmtmulti
|
%type <list> stmtblock stmtmulti
|
||||||
OptTableElementList TableElementList OptInherit definition
|
OptTableElementList TableElementList OptInherit definition
|
||||||
OptWith opt_distinct opt_definition func_args func_args_list
|
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
|
func_as createfunc_opt_list alterfunc_opt_list
|
||||||
aggr_args old_aggr_definition old_aggr_list
|
aggr_args old_aggr_definition old_aggr_list
|
||||||
oper_argtypes RuleActionList RuleActionMulti
|
oper_argtypes RuleActionList RuleActionMulti
|
||||||
@ -278,7 +279,7 @@ static TypeName *TableFuncTypeName(List *columns);
|
|||||||
%type <into> into_clause create_as_target
|
%type <into> into_clause create_as_target
|
||||||
|
|
||||||
%type <defelt> createfunc_opt_item common_func_opt_item
|
%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 <fun_param_mode> arg_class
|
||||||
%type <typnam> func_return func_type
|
%type <typnam> func_return func_type
|
||||||
|
|
||||||
@ -4170,7 +4171,7 @@ opt_nulls_order: NULLS_FIRST { $$ = SORTBY_NULLS_FIRST; }
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
CreateFunctionStmt:
|
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
|
RETURNS func_return createfunc_opt_list opt_definition
|
||||||
{
|
{
|
||||||
CreateFunctionStmt *n = makeNode(CreateFunctionStmt);
|
CreateFunctionStmt *n = makeNode(CreateFunctionStmt);
|
||||||
@ -4182,7 +4183,7 @@ CreateFunctionStmt:
|
|||||||
n->withClause = $9;
|
n->withClause = $9;
|
||||||
$$ = (Node *)n;
|
$$ = (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
|
RETURNS TABLE '(' table_func_column_list ')' createfunc_opt_list opt_definition
|
||||||
{
|
{
|
||||||
CreateFunctionStmt *n = makeNode(CreateFunctionStmt);
|
CreateFunctionStmt *n = makeNode(CreateFunctionStmt);
|
||||||
@ -4195,7 +4196,7 @@ CreateFunctionStmt:
|
|||||||
n->withClause = $12;
|
n->withClause = $12;
|
||||||
$$ = (Node *)n;
|
$$ = (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
|
createfunc_opt_list opt_definition
|
||||||
{
|
{
|
||||||
CreateFunctionStmt *n = makeNode(CreateFunctionStmt);
|
CreateFunctionStmt *n = makeNode(CreateFunctionStmt);
|
||||||
@ -4223,6 +4224,21 @@ func_args_list:
|
|||||||
| func_args_list ',' func_arg { $$ = lappend($1, $3); }
|
| 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
|
* 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
|
* param_name first; accept both since it's likely people will try both
|
||||||
@ -4240,6 +4256,7 @@ func_arg:
|
|||||||
n->name = $2;
|
n->name = $2;
|
||||||
n->argType = $3;
|
n->argType = $3;
|
||||||
n->mode = $1;
|
n->mode = $1;
|
||||||
|
n->defexpr = NULL;
|
||||||
$$ = n;
|
$$ = n;
|
||||||
}
|
}
|
||||||
| param_name arg_class func_type
|
| param_name arg_class func_type
|
||||||
@ -4248,6 +4265,7 @@ func_arg:
|
|||||||
n->name = $1;
|
n->name = $1;
|
||||||
n->argType = $3;
|
n->argType = $3;
|
||||||
n->mode = $2;
|
n->mode = $2;
|
||||||
|
n->defexpr = NULL;
|
||||||
$$ = n;
|
$$ = n;
|
||||||
}
|
}
|
||||||
| param_name func_type
|
| param_name func_type
|
||||||
@ -4256,6 +4274,7 @@ func_arg:
|
|||||||
n->name = $1;
|
n->name = $1;
|
||||||
n->argType = $2;
|
n->argType = $2;
|
||||||
n->mode = FUNC_PARAM_IN;
|
n->mode = FUNC_PARAM_IN;
|
||||||
|
n->defexpr = NULL;
|
||||||
$$ = n;
|
$$ = n;
|
||||||
}
|
}
|
||||||
| arg_class func_type
|
| arg_class func_type
|
||||||
@ -4264,6 +4283,7 @@ func_arg:
|
|||||||
n->name = NULL;
|
n->name = NULL;
|
||||||
n->argType = $2;
|
n->argType = $2;
|
||||||
n->mode = $1;
|
n->mode = $1;
|
||||||
|
n->defexpr = NULL;
|
||||||
$$ = n;
|
$$ = n;
|
||||||
}
|
}
|
||||||
| func_type
|
| func_type
|
||||||
@ -4272,6 +4292,7 @@ func_arg:
|
|||||||
n->name = NULL;
|
n->name = NULL;
|
||||||
n->argType = $1;
|
n->argType = $1;
|
||||||
n->mode = FUNC_PARAM_IN;
|
n->mode = FUNC_PARAM_IN;
|
||||||
|
n->defexpr = NULL;
|
||||||
$$ = n;
|
$$ = 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:
|
createfunc_opt_list:
|
||||||
/* Must be at least one to prevent conflict */
|
/* Must be at least one to prevent conflict */
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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;
|
bool retset;
|
||||||
int nvargs;
|
int nvargs;
|
||||||
FuncDetailCode fdresult;
|
FuncDetailCode fdresult;
|
||||||
|
List *argdefaults;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Most of the rest of the parser just assumes that functions do not have
|
* 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,
|
fdresult = func_get_detail(funcname, fargs, nargs, actual_arg_types,
|
||||||
!func_variadic,
|
!func_variadic,
|
||||||
&funcid, &rettype, &retset, &nvargs,
|
&funcid, &rettype, &retset, &nvargs,
|
||||||
&declared_arg_types);
|
&declared_arg_types, &argdefaults);
|
||||||
if (fdresult == FUNCDETAIL_COERCION)
|
if (fdresult == FUNCDETAIL_COERCION)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -234,6 +235,21 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
|
|||||||
parser_errposition(pstate, location)));
|
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,
|
* enforce consistency with polymorphic argument and return types,
|
||||||
* possibly adjusting return type or declared_arg_types (which will be
|
* possibly adjusting return type or declared_arg_types (which will be
|
||||||
@ -729,7 +745,8 @@ func_get_detail(List *funcname,
|
|||||||
Oid *rettype, /* return value */
|
Oid *rettype, /* return value */
|
||||||
bool *retset, /* return value */
|
bool *retset, /* return value */
|
||||||
int *nvargs, /* return value */
|
int *nvargs, /* return value */
|
||||||
Oid **true_typeids) /* return value */
|
Oid **true_typeids, /* return value */
|
||||||
|
List **argdefaults) /* return value */
|
||||||
{
|
{
|
||||||
FuncCandidateList raw_candidates;
|
FuncCandidateList raw_candidates;
|
||||||
FuncCandidateList best_candidate;
|
FuncCandidateList best_candidate;
|
||||||
@ -870,6 +887,8 @@ func_get_detail(List *funcname,
|
|||||||
*funcid = best_candidate->oid;
|
*funcid = best_candidate->oid;
|
||||||
*nvargs = best_candidate->nvargs;
|
*nvargs = best_candidate->nvargs;
|
||||||
*true_typeids = best_candidate->args;
|
*true_typeids = best_candidate->args;
|
||||||
|
if (argdefaults)
|
||||||
|
*argdefaults = best_candidate->argdefaults;
|
||||||
|
|
||||||
ftup = SearchSysCache(PROCOID,
|
ftup = SearchSysCache(PROCOID,
|
||||||
ObjectIdGetDatum(best_candidate->oid),
|
ObjectIdGetDatum(best_candidate->oid),
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.301 2008/11/07 18:25:06 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.302 2008/12/04 17:51:26 petere Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -700,7 +700,7 @@ ProcessUtility(Node *parsetree,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case T_CreateFunctionStmt: /* CREATE FUNCTION */
|
case T_CreateFunctionStmt: /* CREATE FUNCTION */
|
||||||
CreateFunction((CreateFunctionStmt *) parsetree);
|
CreateFunction((CreateFunctionStmt *) parsetree, queryString);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_AlterFunctionStmt: /* ALTER FUNCTION */
|
case T_AlterFunctionStmt: /* ALTER FUNCTION */
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.287 2008/10/06 20:29:38 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.288 2008/12/04 17:51:27 petere Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -141,7 +141,8 @@ static char *pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
|
|||||||
static char *pg_get_expr_worker(text *expr, Oid relid, char *relname,
|
static char *pg_get_expr_worker(text *expr, Oid relid, char *relname,
|
||||||
int prettyFlags);
|
int prettyFlags);
|
||||||
static int print_function_arguments(StringInfo buf, HeapTuple proctup,
|
static int print_function_arguments(StringInfo buf, HeapTuple proctup,
|
||||||
bool print_table_args);
|
bool print_table_args,
|
||||||
|
bool full);
|
||||||
static void print_function_rettype(StringInfo buf, HeapTuple proctup);
|
static void print_function_rettype(StringInfo buf, HeapTuple proctup);
|
||||||
static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
|
static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
|
||||||
int prettyFlags);
|
int prettyFlags);
|
||||||
@ -1449,7 +1450,7 @@ pg_get_functiondef(PG_FUNCTION_ARGS)
|
|||||||
nsp = get_namespace_name(proc->pronamespace);
|
nsp = get_namespace_name(proc->pronamespace);
|
||||||
appendStringInfo(&buf, "CREATE OR REPLACE FUNCTION %s(",
|
appendStringInfo(&buf, "CREATE OR REPLACE FUNCTION %s(",
|
||||||
quote_qualified_identifier(nsp, name));
|
quote_qualified_identifier(nsp, name));
|
||||||
(void) print_function_arguments(&buf, proctup, false);
|
(void) print_function_arguments(&buf, proctup, false, true);
|
||||||
appendStringInfoString(&buf, ")\n RETURNS ");
|
appendStringInfoString(&buf, ")\n RETURNS ");
|
||||||
print_function_rettype(&buf, proctup);
|
print_function_rettype(&buf, proctup);
|
||||||
appendStringInfo(&buf, "\n LANGUAGE %s\n",
|
appendStringInfo(&buf, "\n LANGUAGE %s\n",
|
||||||
@ -1598,13 +1599,43 @@ pg_get_function_arguments(PG_FUNCTION_ARGS)
|
|||||||
if (!HeapTupleIsValid(proctup))
|
if (!HeapTupleIsValid(proctup))
|
||||||
elog(ERROR, "cache lookup failed for function %u", funcid);
|
elog(ERROR, "cache lookup failed for function %u", funcid);
|
||||||
|
|
||||||
(void) print_function_arguments(&buf, proctup, false);
|
(void) print_function_arguments(&buf, proctup, false, true);
|
||||||
|
|
||||||
ReleaseSysCache(proctup);
|
ReleaseSysCache(proctup);
|
||||||
|
|
||||||
PG_RETURN_TEXT_P(string_to_text(buf.data));
|
PG_RETURN_TEXT_P(string_to_text(buf.data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* pg_get_function_identity_arguments
|
||||||
|
* Get a formatted list of arguments for a function.
|
||||||
|
* This is everything that would go between the parentheses in
|
||||||
|
* ALTER FUNCTION, etc. skip names and defaults/
|
||||||
|
*/
|
||||||
|
Datum
|
||||||
|
pg_get_function_identity_arguments(PG_FUNCTION_ARGS)
|
||||||
|
{
|
||||||
|
Oid funcid = PG_GETARG_OID(0);
|
||||||
|
StringInfoData buf;
|
||||||
|
HeapTuple proctup;
|
||||||
|
|
||||||
|
initStringInfo(&buf);
|
||||||
|
|
||||||
|
proctup = SearchSysCache(PROCOID,
|
||||||
|
ObjectIdGetDatum(funcid),
|
||||||
|
0, 0, 0);
|
||||||
|
if (!HeapTupleIsValid(proctup))
|
||||||
|
elog(ERROR, "cache lookup failed for function %u", funcid);
|
||||||
|
|
||||||
|
(void) print_function_arguments(&buf, proctup, false, false);
|
||||||
|
|
||||||
|
ReleaseSysCache(proctup);
|
||||||
|
|
||||||
|
PG_RETURN_TEXT_P(string_to_text(buf.data));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* pg_get_function_result
|
* pg_get_function_result
|
||||||
* Get a nicely-formatted version of the result type of a function.
|
* Get a nicely-formatted version of the result type of a function.
|
||||||
@ -1649,7 +1680,7 @@ print_function_rettype(StringInfo buf, HeapTuple proctup)
|
|||||||
{
|
{
|
||||||
/* It might be a table function; try to print the arguments */
|
/* It might be a table function; try to print the arguments */
|
||||||
appendStringInfoString(&rbuf, "TABLE(");
|
appendStringInfoString(&rbuf, "TABLE(");
|
||||||
ntabargs = print_function_arguments(&rbuf, proctup, true);
|
ntabargs = print_function_arguments(&rbuf, proctup, true, true);
|
||||||
if (ntabargs > 0)
|
if (ntabargs > 0)
|
||||||
appendStringInfoString(&rbuf, ")");
|
appendStringInfoString(&rbuf, ")");
|
||||||
else
|
else
|
||||||
@ -1672,10 +1703,12 @@ print_function_rettype(StringInfo buf, HeapTuple proctup)
|
|||||||
* append the desired subset of arguments to buf. We print only TABLE
|
* append the desired subset of arguments to buf. We print only TABLE
|
||||||
* arguments when print_table_args is true, and all the others when it's false.
|
* arguments when print_table_args is true, and all the others when it's false.
|
||||||
* Function return value is the number of arguments printed.
|
* Function return value is the number of arguments printed.
|
||||||
|
* When full is false, then don't print argument names and argument defaults.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
print_function_arguments(StringInfo buf, HeapTuple proctup,
|
print_function_arguments(StringInfo buf, HeapTuple proctup,
|
||||||
bool print_table_args)
|
bool print_table_args,
|
||||||
|
bool full)
|
||||||
{
|
{
|
||||||
int numargs;
|
int numargs;
|
||||||
Oid *argtypes;
|
Oid *argtypes;
|
||||||
@ -1683,10 +1716,37 @@ print_function_arguments(StringInfo buf, HeapTuple proctup,
|
|||||||
char *argmodes;
|
char *argmodes;
|
||||||
int argsprinted;
|
int argsprinted;
|
||||||
int i;
|
int i;
|
||||||
|
Datum proargdefaults;
|
||||||
|
List *argdefaults;
|
||||||
|
int nargdefaults;
|
||||||
|
bool isnull;
|
||||||
|
List *dcontext = NIL;
|
||||||
|
|
||||||
numargs = get_func_arg_info(proctup,
|
numargs = get_func_arg_info(proctup,
|
||||||
&argtypes, &argnames, &argmodes);
|
&argtypes, &argnames, &argmodes);
|
||||||
|
|
||||||
|
proargdefaults = SysCacheGetAttr(PROCOID, proctup,
|
||||||
|
Anum_pg_proc_proargdefaults, &isnull);
|
||||||
|
if (!isnull)
|
||||||
|
{
|
||||||
|
char *str;
|
||||||
|
|
||||||
|
str = TextDatumGetCString(proargdefaults);
|
||||||
|
argdefaults = (List *) stringToNode(str);
|
||||||
|
Assert(IsA(argdefaults, List));
|
||||||
|
nargdefaults = list_length(argdefaults);
|
||||||
|
|
||||||
|
/* we will need deparse context */
|
||||||
|
//dcontext = deparse_context_for("", InvalidOid);
|
||||||
|
dcontext = NULL;
|
||||||
|
pfree(str);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
argdefaults = NIL;
|
||||||
|
nargdefaults = 0;
|
||||||
|
}
|
||||||
|
|
||||||
argsprinted = 0;
|
argsprinted = 0;
|
||||||
for (i = 0; i < numargs; i++)
|
for (i = 0; i < numargs; i++)
|
||||||
{
|
{
|
||||||
@ -1723,9 +1783,19 @@ print_function_arguments(StringInfo buf, HeapTuple proctup,
|
|||||||
if (argsprinted)
|
if (argsprinted)
|
||||||
appendStringInfoString(buf, ", ");
|
appendStringInfoString(buf, ", ");
|
||||||
appendStringInfoString(buf, modename);
|
appendStringInfoString(buf, modename);
|
||||||
if (argname && argname[0])
|
if (argname && argname[0] && full)
|
||||||
appendStringInfo(buf, "%s ", argname);
|
appendStringInfo(buf, "%s ", argname);
|
||||||
appendStringInfoString(buf, format_type_be(argtype));
|
appendStringInfoString(buf, format_type_be(argtype));
|
||||||
|
|
||||||
|
/* search given default expression, expect less numargs */
|
||||||
|
if (nargdefaults > 0 && i >= (numargs - nargdefaults) && full)
|
||||||
|
{
|
||||||
|
Node *expr;
|
||||||
|
|
||||||
|
expr = (Node *) list_nth(argdefaults, i - (numargs - nargdefaults));
|
||||||
|
appendStringInfo(buf, " DEFAULT %s", deparse_expression(expr, dcontext, false, false));
|
||||||
|
}
|
||||||
|
|
||||||
argsprinted++;
|
argsprinted++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6002,7 +6072,7 @@ generate_function_name(Oid funcid, int nargs, Oid *argtypes,
|
|||||||
p_result = func_get_detail(list_make1(makeString(proname)),
|
p_result = func_get_detail(list_make1(makeString(proname)),
|
||||||
NIL, nargs, argtypes, false,
|
NIL, nargs, argtypes, false,
|
||||||
&p_funcid, &p_rettype,
|
&p_funcid, &p_rettype,
|
||||||
&p_retset, &p_nvargs, &p_true_typeids);
|
&p_retset, &p_nvargs, &p_true_typeids, NULL);
|
||||||
if ((p_result == FUNCDETAIL_NORMAL || p_result == FUNCDETAIL_AGGREGATE) &&
|
if ((p_result == FUNCDETAIL_NORMAL || p_result == FUNCDETAIL_AGGREGATE) &&
|
||||||
p_funcid == funcid)
|
p_funcid == funcid)
|
||||||
nspname = NULL;
|
nspname = NULL;
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
* by PostgreSQL
|
* by PostgreSQL
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.505 2008/11/09 21:24:32 tgl Exp $
|
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.506 2008/12/04 17:51:27 petere Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -6733,13 +6733,15 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
|
|||||||
PQExpBuffer delqry;
|
PQExpBuffer delqry;
|
||||||
PQExpBuffer asPart;
|
PQExpBuffer asPart;
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
char *funcsig;
|
char *funcsig; /* identity signature */
|
||||||
|
char *funcfullsig; /* full signature */
|
||||||
char *funcsig_tag;
|
char *funcsig_tag;
|
||||||
int ntups;
|
int ntups;
|
||||||
char *proretset;
|
char *proretset;
|
||||||
char *prosrc;
|
char *prosrc;
|
||||||
char *probin;
|
char *probin;
|
||||||
char *funcargs;
|
char *funcargs;
|
||||||
|
char *funciargs;
|
||||||
char *funcresult;
|
char *funcresult;
|
||||||
char *proallargtypes;
|
char *proallargtypes;
|
||||||
char *proargmodes;
|
char *proargmodes;
|
||||||
@ -6782,6 +6784,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
|
|||||||
appendPQExpBuffer(query,
|
appendPQExpBuffer(query,
|
||||||
"SELECT proretset, prosrc, probin, "
|
"SELECT proretset, prosrc, probin, "
|
||||||
"pg_catalog.pg_get_function_arguments(oid) as funcargs, "
|
"pg_catalog.pg_get_function_arguments(oid) as funcargs, "
|
||||||
|
"pg_catalog.pg_get_function_identity_arguments(oid) as funciargs, "
|
||||||
"pg_catalog.pg_get_function_result(oid) as funcresult, "
|
"pg_catalog.pg_get_function_result(oid) as funcresult, "
|
||||||
"provolatile, proisstrict, prosecdef, "
|
"provolatile, proisstrict, prosecdef, "
|
||||||
"proconfig, procost, prorows, "
|
"proconfig, procost, prorows, "
|
||||||
@ -6893,6 +6896,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
|
|||||||
if (g_fout->remoteVersion >= 80400)
|
if (g_fout->remoteVersion >= 80400)
|
||||||
{
|
{
|
||||||
funcargs = PQgetvalue(res, 0, PQfnumber(res, "funcargs"));
|
funcargs = PQgetvalue(res, 0, PQfnumber(res, "funcargs"));
|
||||||
|
funciargs = PQgetvalue(res, 0, PQfnumber(res, "funciargs"));
|
||||||
funcresult = PQgetvalue(res, 0, PQfnumber(res, "funcresult"));
|
funcresult = PQgetvalue(res, 0, PQfnumber(res, "funcresult"));
|
||||||
proallargtypes = proargmodes = proargnames = NULL;
|
proallargtypes = proargmodes = proargnames = NULL;
|
||||||
}
|
}
|
||||||
@ -6901,7 +6905,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
|
|||||||
proallargtypes = PQgetvalue(res, 0, PQfnumber(res, "proallargtypes"));
|
proallargtypes = PQgetvalue(res, 0, PQfnumber(res, "proallargtypes"));
|
||||||
proargmodes = PQgetvalue(res, 0, PQfnumber(res, "proargmodes"));
|
proargmodes = PQgetvalue(res, 0, PQfnumber(res, "proargmodes"));
|
||||||
proargnames = PQgetvalue(res, 0, PQfnumber(res, "proargnames"));
|
proargnames = PQgetvalue(res, 0, PQfnumber(res, "proargnames"));
|
||||||
funcargs = funcresult = NULL;
|
funcargs = funciargs = funcresult = NULL;
|
||||||
}
|
}
|
||||||
provolatile = PQgetvalue(res, 0, PQfnumber(res, "provolatile"));
|
provolatile = PQgetvalue(res, 0, PQfnumber(res, "provolatile"));
|
||||||
proisstrict = PQgetvalue(res, 0, PQfnumber(res, "proisstrict"));
|
proisstrict = PQgetvalue(res, 0, PQfnumber(res, "proisstrict"));
|
||||||
@ -7007,11 +7011,19 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (funcargs)
|
/* funcargs and funciargs are supported from 8.4 */
|
||||||
funcsig = format_function_arguments(finfo, funcargs);
|
if (funciargs)
|
||||||
|
{
|
||||||
|
funcsig = format_function_arguments(finfo, funciargs);
|
||||||
|
funcfullsig = format_function_arguments(finfo, funcargs);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
funcsig = format_function_arguments_old(finfo, nallargs, allargtypes,
|
funcsig = format_function_arguments_old(finfo, nallargs, allargtypes,
|
||||||
argmodes, argnames);
|
argmodes, argnames);
|
||||||
|
funcfullsig = funcsig;
|
||||||
|
}
|
||||||
|
|
||||||
funcsig_tag = format_function_signature(finfo, false);
|
funcsig_tag = format_function_signature(finfo, false);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -7021,7 +7033,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
|
|||||||
fmtId(finfo->dobj.namespace->dobj.name),
|
fmtId(finfo->dobj.namespace->dobj.name),
|
||||||
funcsig);
|
funcsig);
|
||||||
|
|
||||||
appendPQExpBuffer(q, "CREATE FUNCTION %s ", funcsig);
|
appendPQExpBuffer(q, "CREATE FUNCTION %s ", funcfullsig);
|
||||||
if (funcresult)
|
if (funcresult)
|
||||||
appendPQExpBuffer(q, "RETURNS %s", funcresult);
|
appendPQExpBuffer(q, "RETURNS %s", funcresult);
|
||||||
else
|
else
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.510 2008/12/03 13:28:53 heikki Exp $
|
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.511 2008/12/04 17:51:27 petere Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -53,6 +53,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* yyyymmddN */
|
/* yyyymmddN */
|
||||||
#define CATALOG_VERSION_NO 200812031
|
#define CATALOG_VERSION_NO 200812041
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/catalog/namespace.h,v 1.55 2008/07/16 01:30:23 tgl Exp $
|
* $PostgreSQL: pgsql/src/include/catalog/namespace.h,v 1.56 2008/12/04 17:51:27 petere Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -30,6 +30,7 @@ typedef struct _FuncCandidateList
|
|||||||
Oid oid; /* the function or operator's OID */
|
Oid oid; /* the function or operator's OID */
|
||||||
int nargs; /* number of arg types returned */
|
int nargs; /* number of arg types returned */
|
||||||
int nvargs; /* number of args to become variadic array */
|
int nvargs; /* number of args to become variadic array */
|
||||||
|
List *argdefaults; /* list of parameter defaults */
|
||||||
Oid args[1]; /* arg types --- VARIABLE LENGTH ARRAY */
|
Oid args[1]; /* arg types --- VARIABLE LENGTH ARRAY */
|
||||||
} *FuncCandidateList; /* VARIABLE LENGTH STRUCT */
|
} *FuncCandidateList; /* VARIABLE LENGTH STRUCT */
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/catalog/pg_attribute.h,v 1.141 2008/11/09 21:24:33 tgl Exp $
|
* $PostgreSQL: pgsql/src/include/catalog/pg_attribute.h,v 1.142 2008/12/04 17:51:27 petere Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* the genbki.sh script reads this file and generates .bki
|
* the genbki.sh script reads this file and generates .bki
|
||||||
@ -300,15 +300,17 @@ DATA(insert ( 1247 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0));
|
|||||||
{ 1255, {"proretset"}, 16, -1, 1, 11, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
|
{ 1255, {"proretset"}, 16, -1, 1, 11, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
|
||||||
{ 1255, {"provolatile"}, 18, -1, 1, 12, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
|
{ 1255, {"provolatile"}, 18, -1, 1, 12, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
|
||||||
{ 1255, {"pronargs"}, 21, -1, 2, 13, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
|
{ 1255, {"pronargs"}, 21, -1, 2, 13, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
|
||||||
{ 1255, {"prorettype"}, 26, -1, 4, 14, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
|
{ 1255, {"pronargdefaults"}, 21, -1, 2, 14, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
|
||||||
{ 1255, {"proargtypes"}, 30, -1, -1, 15, 1, -1, -1, false, 'p', 'i', true, false, false, true, 0 }, \
|
{ 1255, {"prorettype"}, 26, -1, 4, 15, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
|
||||||
{ 1255, {"proallargtypes"}, 1028, -1, -1, 16, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
|
{ 1255, {"proargtypes"}, 30, -1, -1, 16, 1, -1, -1, false, 'p', 'i', true, false, false, true, 0 }, \
|
||||||
{ 1255, {"proargmodes"}, 1002, -1, -1, 17, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
|
{ 1255, {"proallargtypes"}, 1028, -1, -1, 17, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
|
||||||
{ 1255, {"proargnames"}, 1009, -1, -1, 18, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
|
{ 1255, {"proargmodes"}, 1002, -1, -1, 18, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
|
||||||
{ 1255, {"prosrc"}, 25, -1, -1, 19, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
|
{ 1255, {"proargnames"}, 1009, -1, -1, 19, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
|
||||||
{ 1255, {"probin"}, 17, -1, -1, 20, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
|
{ 1255, {"proargdefaults"}, 25, -1, -1, 20, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
|
||||||
{ 1255, {"proconfig"}, 1009, -1, -1, 21, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
|
{ 1255, {"prosrc"}, 25, -1, -1, 21, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
|
||||||
{ 1255, {"proacl"}, 1034, -1, -1, 22, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }
|
{ 1255, {"probin"}, 17, -1, -1, 22, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
|
||||||
|
{ 1255, {"proconfig"}, 1009, -1, -1, 23, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
|
||||||
|
{ 1255, {"proacl"}, 1034, -1, -1, 24, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }
|
||||||
|
|
||||||
DATA(insert ( 1255 proname 19 -1 NAMEDATALEN 1 0 -1 -1 f p c t f f t 0));
|
DATA(insert ( 1255 proname 19 -1 NAMEDATALEN 1 0 -1 -1 f p c t f f t 0));
|
||||||
DATA(insert ( 1255 pronamespace 26 -1 4 2 0 -1 -1 t p i t f f t 0));
|
DATA(insert ( 1255 pronamespace 26 -1 4 2 0 -1 -1 t p i t f f t 0));
|
||||||
@ -323,15 +325,17 @@ DATA(insert ( 1255 proisstrict 16 -1 1 10 0 -1 -1 t p c t f f t 0));
|
|||||||
DATA(insert ( 1255 proretset 16 -1 1 11 0 -1 -1 t p c t f f t 0));
|
DATA(insert ( 1255 proretset 16 -1 1 11 0 -1 -1 t p c t f f t 0));
|
||||||
DATA(insert ( 1255 provolatile 18 -1 1 12 0 -1 -1 t p c t f f t 0));
|
DATA(insert ( 1255 provolatile 18 -1 1 12 0 -1 -1 t p c t f f t 0));
|
||||||
DATA(insert ( 1255 pronargs 21 -1 2 13 0 -1 -1 t p s t f f t 0));
|
DATA(insert ( 1255 pronargs 21 -1 2 13 0 -1 -1 t p s t f f t 0));
|
||||||
DATA(insert ( 1255 prorettype 26 -1 4 14 0 -1 -1 t p i t f f t 0));
|
DATA(insert ( 1255 pronargdefaults 21 -1 2 14 0 -1 -1 t p s t f f t 0));
|
||||||
DATA(insert ( 1255 proargtypes 30 -1 -1 15 1 -1 -1 f p i t f f t 0));
|
DATA(insert ( 1255 prorettype 26 -1 4 15 0 -1 -1 t p i t f f t 0));
|
||||||
DATA(insert ( 1255 proallargtypes 1028 -1 -1 16 1 -1 -1 f x i f f f t 0));
|
DATA(insert ( 1255 proargtypes 30 -1 -1 16 1 -1 -1 f p i t f f t 0));
|
||||||
DATA(insert ( 1255 proargmodes 1002 -1 -1 17 1 -1 -1 f x i f f f t 0));
|
DATA(insert ( 1255 proallargtypes 1028 -1 -1 17 1 -1 -1 f x i f f f t 0));
|
||||||
DATA(insert ( 1255 proargnames 1009 -1 -1 18 1 -1 -1 f x i f f f t 0));
|
DATA(insert ( 1255 proargmodes 1002 -1 -1 18 1 -1 -1 f x i f f f t 0));
|
||||||
DATA(insert ( 1255 prosrc 25 -1 -1 19 0 -1 -1 f x i f f f t 0));
|
DATA(insert ( 1255 proargnames 1009 -1 -1 19 1 -1 -1 f x i f f f t 0));
|
||||||
DATA(insert ( 1255 probin 17 -1 -1 20 0 -1 -1 f x i f f f t 0));
|
DATA(insert ( 1255 proargdefaults 25 -1 -1 20 0 -1 -1 f x i f f f t 0));
|
||||||
DATA(insert ( 1255 proconfig 1009 -1 -1 21 1 -1 -1 f x i f f f t 0));
|
DATA(insert ( 1255 prosrc 25 -1 -1 21 0 -1 -1 f x i f f f t 0));
|
||||||
DATA(insert ( 1255 proacl 1034 -1 -1 22 1 -1 -1 f x i f f f t 0));
|
DATA(insert ( 1255 probin 17 -1 -1 22 0 -1 -1 f x i f f f t 0));
|
||||||
|
DATA(insert ( 1255 proconfig 1009 -1 -1 23 1 -1 -1 f x i f f f t 0));
|
||||||
|
DATA(insert ( 1255 proacl 1034 -1 -1 24 1 -1 -1 f x i f f f t 0));
|
||||||
DATA(insert ( 1255 ctid 27 0 6 -1 0 -1 -1 f p s t f f t 0));
|
DATA(insert ( 1255 ctid 27 0 6 -1 0 -1 -1 f p s t f f t 0));
|
||||||
DATA(insert ( 1255 oid 26 0 4 -2 0 -1 -1 t p i t f f t 0));
|
DATA(insert ( 1255 oid 26 0 4 -2 0 -1 -1 t p i t f f t 0));
|
||||||
DATA(insert ( 1255 xmin 28 0 4 -3 0 -1 -1 t p i t f f t 0));
|
DATA(insert ( 1255 xmin 28 0 4 -3 0 -1 -1 t p i t f f t 0));
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/catalog/pg_class.h,v 1.108 2008/11/09 21:24:33 tgl Exp $
|
* $PostgreSQL: pgsql/src/include/catalog/pg_class.h,v 1.109 2008/12/04 17:51:27 petere Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* the genbki.sh script reads this file and generates .bki
|
* the genbki.sh script reads this file and generates .bki
|
||||||
@ -125,7 +125,7 @@ DATA(insert OID = 1247 ( pg_type PGNSP 71 PGUID 0 1247 0 0 0 0 0 f f r 28 0 t
|
|||||||
DESCR("");
|
DESCR("");
|
||||||
DATA(insert OID = 1249 ( pg_attribute PGNSP 75 PGUID 0 1249 0 0 0 0 0 f f r 17 0 f f f f f 3 _null_ _null_ ));
|
DATA(insert OID = 1249 ( pg_attribute PGNSP 75 PGUID 0 1249 0 0 0 0 0 f f r 17 0 f f f f f 3 _null_ _null_ ));
|
||||||
DESCR("");
|
DESCR("");
|
||||||
DATA(insert OID = 1255 ( pg_proc PGNSP 81 PGUID 0 1255 0 0 0 0 0 f f r 22 0 t f f f f 3 _null_ _null_ ));
|
DATA(insert OID = 1255 ( pg_proc PGNSP 81 PGUID 0 1255 0 0 0 0 0 f f r 24 0 t f f f f 3 _null_ _null_ ));
|
||||||
DESCR("");
|
DESCR("");
|
||||||
DATA(insert OID = 1259 ( pg_class PGNSP 83 PGUID 0 1259 0 0 0 0 0 f f r 24 0 t f f f f 3 _null_ _null_ ));
|
DATA(insert OID = 1259 ( pg_class PGNSP 83 PGUID 0 1259 0 0 0 0 0 f f r 24 0 t f f f f 3 _null_ _null_ ));
|
||||||
DESCR("");
|
DESCR("");
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/catalog/pg_proc_fn.h,v 1.1 2008/03/27 03:57:34 tgl Exp $
|
* $PostgreSQL: pgsql/src/include/catalog/pg_proc_fn.h,v 1.2 2008/12/04 17:51:27 petere Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -33,7 +33,8 @@ extern Oid ProcedureCreate(const char *procedureName,
|
|||||||
Datum parameterNames,
|
Datum parameterNames,
|
||||||
Datum proconfig,
|
Datum proconfig,
|
||||||
float4 procost,
|
float4 procost,
|
||||||
float4 prorows);
|
float4 prorows,
|
||||||
|
List *parameterDefaults);
|
||||||
|
|
||||||
extern bool function_parse_error_transpose(const char *prosrc);
|
extern bool function_parse_error_transpose(const char *prosrc);
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/commands/defrem.h,v 1.89 2008/06/14 18:04:34 tgl Exp $
|
* $PostgreSQL: pgsql/src/include/commands/defrem.h,v 1.90 2008/12/04 17:51:27 petere Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -45,7 +45,7 @@ extern char *ChooseRelationName(const char *name1, const char *name2,
|
|||||||
extern Oid GetDefaultOpClass(Oid type_id, Oid am_id);
|
extern Oid GetDefaultOpClass(Oid type_id, Oid am_id);
|
||||||
|
|
||||||
/* commands/functioncmds.c */
|
/* commands/functioncmds.c */
|
||||||
extern void CreateFunction(CreateFunctionStmt *stmt);
|
extern void CreateFunction(CreateFunctionStmt *stmt, const char *queryString);
|
||||||
extern void RemoveFunction(RemoveFuncStmt *stmt);
|
extern void RemoveFunction(RemoveFuncStmt *stmt);
|
||||||
extern void RemoveFunctionById(Oid funcOid);
|
extern void RemoveFunctionById(Oid funcOid);
|
||||||
extern void SetFunctionReturnType(Oid funcOid, Oid newRetType);
|
extern void SetFunctionReturnType(Oid funcOid, Oid newRetType);
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.380 2008/12/04 11:42:24 heikki Exp $
|
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.381 2008/12/04 17:51:27 petere Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1686,6 +1686,7 @@ typedef struct FunctionParameter
|
|||||||
char *name; /* parameter name, or NULL if not given */
|
char *name; /* parameter name, or NULL if not given */
|
||||||
TypeName *argType; /* TypeName for parameter type */
|
TypeName *argType; /* TypeName for parameter type */
|
||||||
FunctionParameterMode mode; /* IN/OUT/INOUT */
|
FunctionParameterMode mode; /* IN/OUT/INOUT */
|
||||||
|
Node *defexpr; /* Default expression, or NULL if not given */
|
||||||
} FunctionParameter;
|
} FunctionParameter;
|
||||||
|
|
||||||
typedef struct AlterFunctionStmt
|
typedef struct AlterFunctionStmt
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/parser/parse_func.h,v 1.60 2008/07/16 01:30:23 tgl Exp $
|
* $PostgreSQL: pgsql/src/include/parser/parse_func.h,v 1.61 2008/12/04 17:51:27 petere Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -49,7 +49,8 @@ extern Node *ParseFuncOrColumn(ParseState *pstate,
|
|||||||
extern FuncDetailCode func_get_detail(List *funcname, List *fargs,
|
extern FuncDetailCode func_get_detail(List *funcname, List *fargs,
|
||||||
int nargs, Oid *argtypes, bool expand_variadic,
|
int nargs, Oid *argtypes, bool expand_variadic,
|
||||||
Oid *funcid, Oid *rettype,
|
Oid *funcid, Oid *rettype,
|
||||||
bool *retset, int *nvargs, Oid **true_typeids);
|
bool *retset, int *nvargs, Oid **true_typeids,
|
||||||
|
List **argdefaults);
|
||||||
|
|
||||||
extern int func_match_argtypes(int nargs,
|
extern int func_match_argtypes(int nargs,
|
||||||
Oid *input_typeids,
|
Oid *input_typeids,
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.326 2008/11/03 20:17:20 adunstan Exp $
|
* $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.327 2008/12/04 17:51:28 petere Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -553,6 +553,7 @@ extern Datum pg_get_userbyid(PG_FUNCTION_ARGS);
|
|||||||
extern Datum pg_get_serial_sequence(PG_FUNCTION_ARGS);
|
extern Datum pg_get_serial_sequence(PG_FUNCTION_ARGS);
|
||||||
extern Datum pg_get_functiondef(PG_FUNCTION_ARGS);
|
extern Datum pg_get_functiondef(PG_FUNCTION_ARGS);
|
||||||
extern Datum pg_get_function_arguments(PG_FUNCTION_ARGS);
|
extern Datum pg_get_function_arguments(PG_FUNCTION_ARGS);
|
||||||
|
extern Datum pg_get_function_identity_arguments(PG_FUNCTION_ARGS);
|
||||||
extern Datum pg_get_function_result(PG_FUNCTION_ARGS);
|
extern Datum pg_get_function_result(PG_FUNCTION_ARGS);
|
||||||
extern char *deparse_expression(Node *expr, List *dpcontext,
|
extern char *deparse_expression(Node *expr, List *dpcontext,
|
||||||
bool forceprefix, bool showimplicit);
|
bool forceprefix, bool showimplicit);
|
||||||
|
@ -61,6 +61,14 @@ WHERE prosrc IS NULL OR prosrc = '' OR prosrc = '-';
|
|||||||
-----+---------
|
-----+---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
|
-- pronargdefaults should be 0 iff proargdefaults is null
|
||||||
|
SELECT p.oid, p.proname
|
||||||
|
FROM pg_proc AS p
|
||||||
|
WHERE pronargdefaults <> 0 OR proargdefaults IS NOT NULL;
|
||||||
|
oid | proname
|
||||||
|
-----+---------
|
||||||
|
(0 rows)
|
||||||
|
|
||||||
-- probin should be non-empty for C functions, null everywhere else
|
-- probin should be non-empty for C functions, null everywhere else
|
||||||
SELECT p1.oid, p1.proname
|
SELECT p1.oid, p1.proname
|
||||||
FROM pg_proc as p1
|
FROM pg_proc as p1
|
||||||
|
@ -776,3 +776,190 @@ select pg_typeof(myleast(10, 1, 20, 33)); -- polymorphic input
|
|||||||
integer
|
integer
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
-- test functions with parameter defaults
|
||||||
|
-- test basic functionality
|
||||||
|
create function dfunc(a int = 1, int = 2) returns int as $$
|
||||||
|
select $1 + $2;
|
||||||
|
$$ language sql;
|
||||||
|
select dfunc();
|
||||||
|
dfunc
|
||||||
|
-------
|
||||||
|
3
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select dfunc(10);
|
||||||
|
dfunc
|
||||||
|
-------
|
||||||
|
12
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select dfunc(10, 20);
|
||||||
|
dfunc
|
||||||
|
-------
|
||||||
|
30
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
drop function dfunc(); -- fail
|
||||||
|
ERROR: function dfunc() does not exist
|
||||||
|
drop function dfunc(int); -- fail
|
||||||
|
ERROR: function dfunc(integer) does not exist
|
||||||
|
drop function dfunc(int, int); -- ok
|
||||||
|
-- fail, gap in arguments with defaults
|
||||||
|
create function dfunc(a int = 1, b int) returns int as $$
|
||||||
|
select $1 + $2;
|
||||||
|
$$ language sql;
|
||||||
|
ERROR: parameter without default value specified after parameter with default value
|
||||||
|
-- check implicit coercion
|
||||||
|
create function dfunc(a int DEFAULT 1.0, int DEFAULT '-1') returns int as $$
|
||||||
|
select $1 + $2;
|
||||||
|
$$ language sql;
|
||||||
|
select dfunc();
|
||||||
|
dfunc
|
||||||
|
-------
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
create function dfunc(a text DEFAULT 'Hello', b text DEFAULT 'World') returns text as $$
|
||||||
|
select $1 || ', ' || $2;
|
||||||
|
$$ language sql;
|
||||||
|
select dfunc(); -- fail; which dfunc should be called? int or text
|
||||||
|
ERROR: functions with parameter defaults dfunc(text, text) and dfunc(integer, integer) are ambiguous
|
||||||
|
select dfunc('Hi'); -- ok
|
||||||
|
dfunc
|
||||||
|
-----------
|
||||||
|
Hi, World
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select dfunc('Hi', 'City'); -- ok
|
||||||
|
dfunc
|
||||||
|
----------
|
||||||
|
Hi, City
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select dfunc(0); -- ok
|
||||||
|
dfunc
|
||||||
|
-------
|
||||||
|
-1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select dfunc(10, 20); -- ok
|
||||||
|
dfunc
|
||||||
|
-------
|
||||||
|
30
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
drop function dfunc(int, int);
|
||||||
|
drop function dfunc(text, text);
|
||||||
|
create function dfunc(int = 1, int = 2) returns int as $$
|
||||||
|
select 2;
|
||||||
|
$$ language sql;
|
||||||
|
create function dfunc(int = 1, int = 2, int = 3, int = 4) returns int as $$
|
||||||
|
select 4;
|
||||||
|
$$ language sql;
|
||||||
|
-- Now, dfunc(nargs = 2) and dfunc(nargs = 4) are ambiguous when called
|
||||||
|
-- with 0 or 1 arguments. For 2 arguments, a normall call of
|
||||||
|
-- dfunc(nargs = 2) takes place.
|
||||||
|
select dfunc(); -- fail
|
||||||
|
ERROR: functions with parameter defaults dfunc(integer, integer, integer, integer) and dfunc(integer, integer) are ambiguous
|
||||||
|
select dfunc(1); -- fail
|
||||||
|
ERROR: functions with parameter defaults dfunc(integer, integer, integer, integer) and dfunc(integer, integer) are ambiguous
|
||||||
|
select dfunc(1, 2); -- ok
|
||||||
|
dfunc
|
||||||
|
-------
|
||||||
|
2
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select dfunc(1, 2, 3); -- ok
|
||||||
|
dfunc
|
||||||
|
-------
|
||||||
|
4
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select dfunc(1, 2, 3, 4); -- ok
|
||||||
|
dfunc
|
||||||
|
-------
|
||||||
|
4
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
drop function dfunc(int, int);
|
||||||
|
drop function dfunc(int, int, int, int);
|
||||||
|
-- default values are not allowed for output parameters
|
||||||
|
create function dfunc(out int = 20) returns int as $$
|
||||||
|
select 1;
|
||||||
|
$$ language sql;
|
||||||
|
ERROR: only IN and INOUT parameters can have default values
|
||||||
|
-- polymorphic parameter test
|
||||||
|
create function dfunc(anyelement = 'World'::text) returns text as $$
|
||||||
|
select 'Hello, ' || $1::text;
|
||||||
|
$$ language sql;
|
||||||
|
select dfunc();
|
||||||
|
dfunc
|
||||||
|
--------------
|
||||||
|
Hello, World
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select dfunc(0);
|
||||||
|
dfunc
|
||||||
|
----------
|
||||||
|
Hello, 0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select dfunc(to_date('20081215','YYYYMMDD'));
|
||||||
|
dfunc
|
||||||
|
-------------------
|
||||||
|
Hello, 12-15-2008
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select dfunc('City'::text);
|
||||||
|
dfunc
|
||||||
|
-------------
|
||||||
|
Hello, City
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
drop function dfunc(anyelement);
|
||||||
|
-- check null values
|
||||||
|
create function dfunc(int = null, int = null, int = null) returns int[] as $$
|
||||||
|
select array[$1, $2, $3];
|
||||||
|
$$ language sql;
|
||||||
|
select dfunc(1);
|
||||||
|
dfunc
|
||||||
|
---------------
|
||||||
|
{1,NULL,NULL}
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select dfunc(1, 2);
|
||||||
|
dfunc
|
||||||
|
------------
|
||||||
|
{1,2,NULL}
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select dfunc(1, 2, 3);
|
||||||
|
dfunc
|
||||||
|
---------
|
||||||
|
{1,2,3}
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
drop function dfunc(int, int, int);
|
||||||
|
-- The conflict detection algorithm doesn't consider the actual parameter
|
||||||
|
-- types. It detects any possible conflict for n arguments for some
|
||||||
|
-- function. This is unwanted behavior, but solving it needs a move of
|
||||||
|
-- coercion routines.
|
||||||
|
create function dfunc(int = 1, int = 2, int = 3) returns int as $$
|
||||||
|
select 3;
|
||||||
|
$$ language sql;
|
||||||
|
create function dfunc(int = 1, int = 2) returns int as $$
|
||||||
|
select 2;
|
||||||
|
$$ language sql;
|
||||||
|
-- for n = 1 dfunc(narg=2) and dfunc(narg=3) are ambiguous
|
||||||
|
select dfunc(1); -- fail
|
||||||
|
ERROR: functions with parameter defaults dfunc(integer, integer, integer) and dfunc(integer, integer) are ambiguous
|
||||||
|
create function dfunc(text) returns text as $$
|
||||||
|
select $1;
|
||||||
|
$$ language sql;
|
||||||
|
-- Will fail, it detects ambiguity between dfunc(int, int, int) and
|
||||||
|
-- dfunc(int, int), but dfunc(text) isn't in conflict with either.
|
||||||
|
select dfunc('Hi');
|
||||||
|
ERROR: functions with parameter defaults dfunc(integer, integer, integer) and dfunc(integer, integer) are ambiguous
|
||||||
|
drop function dfunc(int, int, int);
|
||||||
|
drop function dfunc(int, int);
|
||||||
|
drop function dfunc(text);
|
||||||
|
@ -62,6 +62,11 @@ SELECT p1.oid, p1.proname
|
|||||||
FROM pg_proc as p1
|
FROM pg_proc as p1
|
||||||
WHERE prosrc IS NULL OR prosrc = '' OR prosrc = '-';
|
WHERE prosrc IS NULL OR prosrc = '' OR prosrc = '-';
|
||||||
|
|
||||||
|
-- pronargdefaults should be 0 iff proargdefaults is null
|
||||||
|
SELECT p.oid, p.proname
|
||||||
|
FROM pg_proc AS p
|
||||||
|
WHERE pronargdefaults <> 0 OR proargdefaults IS NOT NULL;
|
||||||
|
|
||||||
-- probin should be non-empty for C functions, null everywhere else
|
-- probin should be non-empty for C functions, null everywhere else
|
||||||
SELECT p1.oid, p1.proname
|
SELECT p1.oid, p1.proname
|
||||||
FROM pg_proc as p1
|
FROM pg_proc as p1
|
||||||
|
@ -480,3 +480,117 @@ select pg_typeof('' || ''); -- text
|
|||||||
select pg_typeof(pg_typeof(0)); -- regtype
|
select pg_typeof(pg_typeof(0)); -- regtype
|
||||||
select pg_typeof(array[1.2,55.5]); -- numeric[]
|
select pg_typeof(array[1.2,55.5]); -- numeric[]
|
||||||
select pg_typeof(myleast(10, 1, 20, 33)); -- polymorphic input
|
select pg_typeof(myleast(10, 1, 20, 33)); -- polymorphic input
|
||||||
|
|
||||||
|
-- test functions with parameter defaults
|
||||||
|
-- test basic functionality
|
||||||
|
create function dfunc(a int = 1, int = 2) returns int as $$
|
||||||
|
select $1 + $2;
|
||||||
|
$$ language sql;
|
||||||
|
|
||||||
|
select dfunc();
|
||||||
|
select dfunc(10);
|
||||||
|
select dfunc(10, 20);
|
||||||
|
|
||||||
|
drop function dfunc(); -- fail
|
||||||
|
drop function dfunc(int); -- fail
|
||||||
|
drop function dfunc(int, int); -- ok
|
||||||
|
|
||||||
|
-- fail, gap in arguments with defaults
|
||||||
|
create function dfunc(a int = 1, b int) returns int as $$
|
||||||
|
select $1 + $2;
|
||||||
|
$$ language sql;
|
||||||
|
|
||||||
|
-- check implicit coercion
|
||||||
|
create function dfunc(a int DEFAULT 1.0, int DEFAULT '-1') returns int as $$
|
||||||
|
select $1 + $2;
|
||||||
|
$$ language sql;
|
||||||
|
select dfunc();
|
||||||
|
create function dfunc(a text DEFAULT 'Hello', b text DEFAULT 'World') returns text as $$
|
||||||
|
select $1 || ', ' || $2;
|
||||||
|
$$ language sql;
|
||||||
|
|
||||||
|
select dfunc(); -- fail; which dfunc should be called? int or text
|
||||||
|
select dfunc('Hi'); -- ok
|
||||||
|
select dfunc('Hi', 'City'); -- ok
|
||||||
|
select dfunc(0); -- ok
|
||||||
|
select dfunc(10, 20); -- ok
|
||||||
|
|
||||||
|
drop function dfunc(int, int);
|
||||||
|
drop function dfunc(text, text);
|
||||||
|
|
||||||
|
create function dfunc(int = 1, int = 2) returns int as $$
|
||||||
|
select 2;
|
||||||
|
$$ language sql;
|
||||||
|
|
||||||
|
create function dfunc(int = 1, int = 2, int = 3, int = 4) returns int as $$
|
||||||
|
select 4;
|
||||||
|
$$ language sql;
|
||||||
|
|
||||||
|
-- Now, dfunc(nargs = 2) and dfunc(nargs = 4) are ambiguous when called
|
||||||
|
-- with 0 or 1 arguments. For 2 arguments, a normall call of
|
||||||
|
-- dfunc(nargs = 2) takes place.
|
||||||
|
|
||||||
|
select dfunc(); -- fail
|
||||||
|
select dfunc(1); -- fail
|
||||||
|
select dfunc(1, 2); -- ok
|
||||||
|
select dfunc(1, 2, 3); -- ok
|
||||||
|
select dfunc(1, 2, 3, 4); -- ok
|
||||||
|
|
||||||
|
drop function dfunc(int, int);
|
||||||
|
drop function dfunc(int, int, int, int);
|
||||||
|
|
||||||
|
-- default values are not allowed for output parameters
|
||||||
|
create function dfunc(out int = 20) returns int as $$
|
||||||
|
select 1;
|
||||||
|
$$ language sql;
|
||||||
|
|
||||||
|
-- polymorphic parameter test
|
||||||
|
create function dfunc(anyelement = 'World'::text) returns text as $$
|
||||||
|
select 'Hello, ' || $1::text;
|
||||||
|
$$ language sql;
|
||||||
|
|
||||||
|
select dfunc();
|
||||||
|
select dfunc(0);
|
||||||
|
select dfunc(to_date('20081215','YYYYMMDD'));
|
||||||
|
select dfunc('City'::text);
|
||||||
|
|
||||||
|
drop function dfunc(anyelement);
|
||||||
|
|
||||||
|
-- check null values
|
||||||
|
create function dfunc(int = null, int = null, int = null) returns int[] as $$
|
||||||
|
select array[$1, $2, $3];
|
||||||
|
$$ language sql;
|
||||||
|
|
||||||
|
select dfunc(1);
|
||||||
|
select dfunc(1, 2);
|
||||||
|
select dfunc(1, 2, 3);
|
||||||
|
|
||||||
|
drop function dfunc(int, int, int);
|
||||||
|
|
||||||
|
-- The conflict detection algorithm doesn't consider the actual parameter
|
||||||
|
-- types. It detects any possible conflict for n arguments for some
|
||||||
|
-- function. This is unwanted behavior, but solving it needs a move of
|
||||||
|
-- coercion routines.
|
||||||
|
|
||||||
|
create function dfunc(int = 1, int = 2, int = 3) returns int as $$
|
||||||
|
select 3;
|
||||||
|
$$ language sql;
|
||||||
|
|
||||||
|
create function dfunc(int = 1, int = 2) returns int as $$
|
||||||
|
select 2;
|
||||||
|
$$ language sql;
|
||||||
|
|
||||||
|
-- for n = 1 dfunc(narg=2) and dfunc(narg=3) are ambiguous
|
||||||
|
select dfunc(1); -- fail
|
||||||
|
|
||||||
|
create function dfunc(text) returns text as $$
|
||||||
|
select $1;
|
||||||
|
$$ language sql;
|
||||||
|
|
||||||
|
-- Will fail, it detects ambiguity between dfunc(int, int, int) and
|
||||||
|
-- dfunc(int, int), but dfunc(text) isn't in conflict with either.
|
||||||
|
select dfunc('Hi');
|
||||||
|
|
||||||
|
drop function dfunc(int, int, int);
|
||||||
|
drop function dfunc(int, int);
|
||||||
|
drop function dfunc(text);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user