variadic function support

Started by Pavel Stehuleabout 18 years ago42 messagespatches
Jump to latest
#1Pavel Stehule
pavel.stehule@gmail.com

Hello

this patch enhance current syntax of CREATE FUNCTION statement. It
allows creating functions with variable number of arguments. This
version is different than last my patches. It doesn't need patching
PL. Basic idea is transformation of real arguments (related to
declared variadic argument) to array. All changes are mostly in
parser.

Demo:
CREATE FUNCTION public.least(double precision[]) RETURNS double precision AS $$
SELECT min($1[i])
FROM generate_subscripts($1,1) g(i)
$$ LANGUAGE SQL VARIADIC;

SELECT public.least(3,2,1);
least
-------
1
(1 row)

SELECT public.least(3,2,1,0,-1);
least
-------
-1
CREATE FUNCTION concat(varchar, anyarray) RETURNS varchar AS $$
SELECT array_to_string($2, $1);
$$ LANGUAGE SQL VARIADIC;

SELECT concat('-',2008,10,12);
concat
------------
2008-10-12
(1 row)

Regards
Pavel Stehule

Attachments:

variadic.1.0.0.diff.gzapplication/x-gzip; name=variadic.1.0.0.diff.gzDownload+0-1
#2Andrew Dunstan
andrew@dunslane.net
In reply to: Pavel Stehule (#1)
Re: variadic function support

Pavel Stehule wrote:

Hello

this patch enhance current syntax of CREATE FUNCTION statement. It
allows creating functions with variable number of arguments. This
version is different than last my patches. It doesn't need patching
PL. Basic idea is transformation of real arguments (related to
declared variadic argument) to array. All changes are mostly in
parser.

Demo:
CREATE FUNCTION public.least(double precision[]) RETURNS double precision AS $$
SELECT min($1[i])
FROM generate_subscripts($1,1) g(i)
$$ LANGUAGE SQL VARIADIC;

SELECT public.least(3,2,1);
least
-------
1
(1 row)

SELECT public.least(3,2,1,0,-1);
least
-------
-1
CREATE FUNCTION concat(varchar, anyarray) RETURNS varchar AS $$
SELECT array_to_string($2, $1);
$$ LANGUAGE SQL VARIADIC;

SELECT concat('-',2008,10,12);
concat
------------
2008-10-12
(1 row)

And what about a function that takes 2 arrays as arguments?

This proposal strikes me as half-baked. Either we need proper and full
support for variadic functions, or we don't, but I don't think we need
syntactic sugar like the above (or maybe in this case it's really
syntactic saccharine).

cheers

andrew

#3Tom Lane
tgl@sss.pgh.pa.us
In reply to: Andrew Dunstan (#2)
Re: variadic function support

Andrew Dunstan <andrew@dunslane.net> writes:

This proposal strikes me as half-baked. Either we need proper and full
support for variadic functions, or we don't, but I don't think we need
syntactic sugar like the above (or maybe in this case it's really
syntactic saccharine).

What would you consider "proper and full support"?

regards, tom lane

#4Andrew Dunstan
andrew@dunslane.net
In reply to: Tom Lane (#3)
Re: variadic function support

Tom Lane wrote:

Andrew Dunstan <andrew@dunslane.net> writes:

This proposal strikes me as half-baked. Either we need proper and full
support for variadic functions, or we don't, but I don't think we need
syntactic sugar like the above (or maybe in this case it's really
syntactic saccharine).

What would you consider "proper and full support"?

I don't know. But this doesn't feel like it.

I'm not even sure it's possible to so in any sane way alongside overloading.

cheers

andrew

#5Tom Lane
tgl@sss.pgh.pa.us
In reply to: Andrew Dunstan (#4)
Re: variadic function support

Andrew Dunstan <andrew@dunslane.net> writes:

Tom Lane wrote:

What would you consider "proper and full support"?

I don't know. But this doesn't feel like it.

That's a fairly weak argument for rejecting a patch that provides a
feature many people have asked for.

I thought the patch was pretty clever, actually. The main functionality
complaint someone might level against it is that all the variadic
arguments have to be (coercible to) the same type. However, that's
still pretty useful, and I don't see a reasonable solution that provides
more generality than that in a type-safe way. I'm quite happy that you
can't write sprintf() using this ;-)

A different line of argument is whether this functionality is
sufficiently badly needed that we should get out in front of the SQL
standard on providing it, and risk being stuck with legacy behavior
if they eventually adopt some other mechanism to solve the same problem.
I'm not sure how worried I am about that. There are certainly a
boatload of Postgres-isms in and around CREATE FUNCTION already,
so it's hard to make a case against "just one more".

regards, tom lane

#6Andrew Dunstan
andrew@dunslane.net
In reply to: Tom Lane (#5)
Re: variadic function support

Tom Lane wrote:

Andrew Dunstan <andrew@dunslane.net> writes:

Tom Lane wrote:

What would you consider "proper and full support"?

I don't know. But this doesn't feel like it.

That's a fairly weak argument for rejecting a patch that provides a
feature many people have asked for.

OK. Let me be a bit more specific. I think (forcing myself to be a bit
more analytic than I have been up to now) my main objection is that the
variadic part of the parameters should be marked explicitly in the
formal parameter list.

I don't mind having it limited to a single typed array - as you say we
probably don't want someone implementing sprintf.

But if I have

foo( a text, b int[])

it looks odd if both these calls are legal:

foo('a',1,2,3,)
foo('a',ARRAY[1,2,3])

which I understand would be the case with the current patch.

I'm also still curious to know how the following would be handled:

foo(a text[], b text[])

cheers

andrew

#7Tom Lane
tgl@sss.pgh.pa.us
In reply to: Andrew Dunstan (#6)
Re: variadic function support

Andrew Dunstan <andrew@dunslane.net> writes:

But if I have
foo( a text, b int[])
it looks odd if both these calls are legal:
foo('a',1,2,3,)
foo('a',ARRAY[1,2,3])
which I understand would be the case with the current patch.

Maybe I misunderstand what is supposed to happen, but I believe that
if the function is marked VARIADIC then the second case would in fact
be rejected: the signature of the function for parameter-matching
purposes is text followed by one or more ints, never text and int[].

I'm also still curious to know how the following would be handled:
foo(a text[], b text[])

I think a is just text[], full stop. Only the last parameter is
interpreted differently for variadic.

Your point about the syntax is good though. It would be better if
the syntax were like

create function foo (a text, variadic b int[])

or maybe even better

create function foo (a text, variadic b int)

since (a) this makes it much more obvious to the reader what the
function might match, and (b) it leaves the door open for marking
multiple parameters as variadic, if we can figure out what that means.

regards, tom lane

#8Andrew Dunstan
andrew@dunslane.net
In reply to: Tom Lane (#7)
Re: variadic function support

Tom Lane wrote:

Your point about the syntax is good though. It would be better if
the syntax were like

create function foo (a text, variadic b int[])

or maybe even better

create function foo (a text, variadic b int)

since (a) this makes it much more obvious to the reader what the
function might match, and (b) it leaves the door open for marking
multiple parameters as variadic, if we can figure out what that means.

Yes. I understand from the family Java expert that (surface syntax
issues aside) the second is similar to the way Java does this, in fact,
so there's some precedent. That would mean that your first would
actually mean each variadic arg has to be an array of ints, which we
might well want to provide for.

So with that modification I'll be lots happier with the feature.

cheers

andrew

#9Pavel Stehule
pavel.stehule@gmail.com
In reply to: Andrew Dunstan (#2)
Re: variadic function support

2008/6/23 Andrew Dunstan <andrew@dunslane.net>:

And what about a function that takes 2 arrays as arguments?

only last argument is evaluated as variadic

so function

create or replace function foo(a int[], b int[]) ... variadic

is called
select foo(array[1,2,3], 1,2,3,4,5,6)

This proposal strikes me as half-baked. Either we need proper and full
support for variadic functions, or we don't, but I don't think we need
syntactic sugar like the above (or maybe in this case it's really syntactic
saccharine).

there is some functions like Oracle's least,greater, decode that needs
this feature. So I can write wrappers. For me most important are new
possibility for C procedures. All this work is related to my JSON
support proposal.

Pavel

Show quoted text

cheers

andrew

#10Pavel Stehule
pavel.stehule@gmail.com
In reply to: Andrew Dunstan (#8)
Re: variadic function support

2008/6/24 Andrew Dunstan <andrew@dunslane.net>:

Tom Lane wrote:

Your point about the syntax is good though. It would be better if
the syntax were like

create function foo (a text, variadic b int[])

or maybe even better

create function foo (a text, variadic b int)

since (a) this makes it much more obvious to the reader what the
function might match, and (b) it leaves the door open for marking
multiple parameters as variadic, if we can figure out what that means.

Yes. I understand from the family Java expert that (surface syntax issues
aside) the second is similar to the way Java does this, in fact, so there's
some precedent. That would mean that your first would actually mean each
variadic arg has to be an array of ints, which we might well want to provide
for.

So with that modification I'll be lots happier with the feature.

I don't see problem with your syntax. It well block combination OUT
and VARIADIC parameter - my one request, variadic parameter have to be
array. It's more consistent with following procedure implementation -
inside procedures is really array.

sample:
CREATE OR REPLACE least(varidic values numeric[]) --< ARRAY
RETURNS numeric AS $$
SELECT $1[i] --< ARRAY
FROM

Regards
Pavel Stehule

p.s. with one exception "any", because there isn't possible array from "any"

Show quoted text

cheers

andrew

#11Pavel Stehule
pavel.stehule@gmail.com
In reply to: Tom Lane (#7)
Re: variadic function support

2008/6/24 Tom Lane <tgl@sss.pgh.pa.us>:

Andrew Dunstan <andrew@dunslane.net> writes:

But if I have
foo( a text, b int[])
it looks odd if both these calls are legal:
foo('a',1,2,3,)
foo('a',ARRAY[1,2,3])
which I understand would be the case with the current patch.

Maybe I misunderstand what is supposed to happen, but I believe that
if the function is marked VARIADIC then the second case would in fact
be rejected: the signature of the function for parameter-matching
purposes is text followed by one or more ints, never text and int[].

I'm also still curious to know how the following would be handled:
foo(a text[], b text[])

I think a is just text[], full stop. Only the last parameter is
interpreted differently for variadic.

Your point about the syntax is good though. It would be better if
the syntax were like

create function foo (a text, variadic b int[])

or maybe even better

create function foo (a text, variadic b int)

since (a) this makes it much more obvious to the reader what the
function might match, and (b) it leaves the door open for marking
multiple parameters as variadic, if we can figure out what that means.

(b) has one disadvantage - argument type is different than real
parameter - and internally it is little bit cleaner (doesn't need
changes in executor). So there is two forces in opposite. a) clean
function's declaration, b) clean function definition. This syntax is
limited - I am not able implement all cases of Oracle's decode
functions - but I hope it's good compromise between functionality and
simplicity.

note - variant b doesn't block multiple parameters as variadic - is
same case as a. array or not array is unimportant - I need different
types so I can choose what is first variadic argument and what is
second.

Academic question is using structured arrays - some like

create or replace function decode(s_value anyelement1, variadic
(s_value anyalement1, o_value anyelement)[])
returns anyelement as $$
select ($2[i]).o_value
from generate_subcripts($1,1) g(i)
where ($2[i]).s_value = $1;
$$ language sql;

regards
Pavel Stehule

Show quoted text

regards, tom lane

#12Pavel Stehule
pavel.stehule@gmail.com
In reply to: Tom Lane (#7)
Re: variadic function support

Hello

this version implements syntax based on argmodes.

CREATE FUNCTION mleast(variadic numeric[]) RETURNS numeric AS $$
SELECT min($1[i])
FROM generate_subscripts($1,1) g(i);
$$ LANGUAGE SQL;

Regards
Pavel Stehule

2008/6/24 Tom Lane <tgl@sss.pgh.pa.us>:

Show quoted text

Andrew Dunstan <andrew@dunslane.net> writes:

But if I have
foo( a text, b int[])
it looks odd if both these calls are legal:
foo('a',1,2,3,)
foo('a',ARRAY[1,2,3])
which I understand would be the case with the current patch.

Maybe I misunderstand what is supposed to happen, but I believe that
if the function is marked VARIADIC then the second case would in fact
be rejected: the signature of the function for parameter-matching
purposes is text followed by one or more ints, never text and int[].

I'm also still curious to know how the following would be handled:
foo(a text[], b text[])

I think a is just text[], full stop. Only the last parameter is
interpreted differently for variadic.

Your point about the syntax is good though. It would be better if
the syntax were like

create function foo (a text, variadic b int[])

or maybe even better

create function foo (a text, variadic b int)

since (a) this makes it much more obvious to the reader what the
function might match, and (b) it leaves the door open for marking
multiple parameters as variadic, if we can figure out what that means.

regards, tom lane

Attachments:

variadic.2.0.0.difftext/x-patch; name=variadic.2.0.0.diffDownload+427-109
#13Tom Lane
tgl@sss.pgh.pa.us
In reply to: Pavel Stehule (#10)
Re: variadic function support

"Pavel Stehule" <pavel.stehule@gmail.com> writes:

Tom Lane wrote:

Your point about the syntax is good though. It would be better if
the syntax were like
create function foo (a text, variadic b int[])
or maybe even better
create function foo (a text, variadic b int)

I don't see problem with your syntax. It well block combination OUT
and VARIADIC parameter - my one request, variadic parameter have to be
array.

Well, we should certainly store the parameter type as an array in
proargtypes, because that makes this feature transparent to all the
PLs. However, it doesn't follow that the CREATE FUNCTION syntax
has to specify the array type rather than the element type. I think
the Java precedent might be good reason to go with using the element
type in the function declaration.

regards, tom lane

#14Pavel Stehule
pavel.stehule@gmail.com
In reply to: Tom Lane (#13)
Re: variadic function support

2008/6/25 Tom Lane <tgl@sss.pgh.pa.us>:

"Pavel Stehule" <pavel.stehule@gmail.com> writes:

Tom Lane wrote:

Your point about the syntax is good though. It would be better if
the syntax were like
create function foo (a text, variadic b int[])
or maybe even better
create function foo (a text, variadic b int)

I don't see problem with your syntax. It well block combination OUT
and VARIADIC parameter - my one request, variadic parameter have to be
array.

Well, we should certainly store the parameter type as an array in
proargtypes, because that makes this feature transparent to all the
PLs. However, it doesn't follow that the CREATE FUNCTION syntax
has to specify the array type rather than the element type. I think
the Java precedent might be good reason to go with using the element
type in the function declaration.

There is only one break - psql functions description. It needs
publishing get_element_type function and ofcourse all managers need
update.

regards
Pavel

Show quoted text

regards, tom lane

#15Pavel Stehule
pavel.stehule@gmail.com
In reply to: Tom Lane (#13)
Re: variadic function support

2008/6/25 Tom Lane <tgl@sss.pgh.pa.us>:

"Pavel Stehule" <pavel.stehule@gmail.com> writes:

Tom Lane wrote:

Your point about the syntax is good though. It would be better if
the syntax were like
create function foo (a text, variadic b int[])
or maybe even better
create function foo (a text, variadic b int)

I don't see problem with your syntax. It well block combination OUT
and VARIADIC parameter - my one request, variadic parameter have to be
array.

Well, we should certainly store the parameter type as an array in
proargtypes, because that makes this feature transparent to all the
PLs. However, it doesn't follow that the CREATE FUNCTION syntax
has to specify the array type rather than the element type. I think
the Java precedent might be good reason to go with using the element
type in the function declaration.

it's strange.I looked for some info
http://en.wikipedia.org/wiki/Variadic_function#Variadic_functions_in_C.23_and_Java

C# use array

Does somebody know some about variadic functions in ADA?

Regards
Pavel Stehule

Show quoted text

regards, tom lane

#16Pavel Stehule
pavel.stehule@gmail.com
In reply to: Tom Lane (#13)
Re: variadic function support

2008/6/25 Tom Lane <tgl@sss.pgh.pa.us>:

"Pavel Stehule" <pavel.stehule@gmail.com> writes:

Tom Lane wrote:

Your point about the syntax is good though. It would be better if
the syntax were like
create function foo (a text, variadic b int[])
or maybe even better
create function foo (a text, variadic b int)

I don't see problem with your syntax. It well block combination OUT
and VARIADIC parameter - my one request, variadic parameter have to be
array.

Well, we should certainly store the parameter type as an array in
proargtypes, because that makes this feature transparent to all the
PLs. However, it doesn't follow that the CREATE FUNCTION syntax
has to specify the array type rather than the element type. I think
the Java precedent might be good reason to go with using the element
type in the function declaration.

I afraid so Java syntax isn't good inspiration
http://www.java-tips.org/java-se-tips/java.lang/using-the-varargs-language-feature.html
http://www.clanproductions.com/java5.html

they use symbol ... like specific synonym to [].
public Method getMethod(String name, Class... parameterTypes)

I didn't find any info about vararg in Oracle - it uses collection and
it allows implicit constructors for emulation o variadic functions -
but "variadic" argument isn't scalar too. So I invite any opinions
about it.

Regards
Pavel Stehule

Show quoted text

regards, tom lane

#17Andrew Dunstan
andrew@dunslane.net
In reply to: Pavel Stehule (#16)
Re: variadic function support

Pavel Stehule wrote:

I afraid so Java syntax isn't good inspiration
http://www.java-tips.org/java-se-tips/java.lang/using-the-varargs-language-feature.html
http://www.clanproductions.com/java5.html

they use symbol ... like specific synonym to [].
public Method getMethod(String name, Class... parameterTypes)

Well, ... is really more the equivalent of your "variadic" keyword, I think.

public Method getMethod(String name, Class[] ... parameterTypes)

would mean each variadic argument would be an array of Class.

cheers

andrew

#18Pavel Stehule
pavel.stehule@gmail.com
In reply to: Tom Lane (#13)
Re: variadic function support

2008/6/25 Tom Lane <tgl@sss.pgh.pa.us>:

"Pavel Stehule" <pavel.stehule@gmail.com> writes:

Tom Lane wrote:

Your point about the syntax is good though. It would be better if
the syntax were like
create function foo (a text, variadic b int[])
or maybe even better
create function foo (a text, variadic b int)

I don't see problem with your syntax. It well block combination OUT
and VARIADIC parameter - my one request, variadic parameter have to be
array.

Well, we should certainly store the parameter type as an array in
proargtypes, because that makes this feature transparent to all the
PLs. However, it doesn't follow that the CREATE FUNCTION syntax
has to specify the array type rather than the element type. I think
the Java precedent might be good reason to go with using the element
type in the function declaration.

I am playing with this now and two versions of proargtypes is 30% more
ugly code - mostly pg_dump and paradoxically remove function -
because currently RemoveFuncStatement lost argmode, so I am missing
info about variadic parameter and I can't simply transformation from
element to array. I thing, it isn't good way.

Regards
Pavel Stehule

Show quoted text

regards, tom lane

#19Pavel Stehule
pavel.stehule@gmail.com
In reply to: Tom Lane (#13)
Re: variadic function support

2008/6/25 Tom Lane <tgl@sss.pgh.pa.us>:

"Pavel Stehule" <pavel.stehule@gmail.com> writes:

Tom Lane wrote:

Your point about the syntax is good though. It would be better if
the syntax were like
create function foo (a text, variadic b int[])
or maybe even better
create function foo (a text, variadic b int)

I don't see problem with your syntax. It well block combination OUT
and VARIADIC parameter - my one request, variadic parameter have to be
array.

Well, we should certainly store the parameter type as an array in
proargtypes, because that makes this feature transparent to all the
PLs. However, it doesn't follow that the CREATE FUNCTION syntax
has to specify the array type rather than the element type. I think
the Java precedent might be good reason to go with using the element
type in the function declaration.

regards, tom lane

Hello

this is third variant with variadic argumen as scalar. But I still
strongly prefer second variant with conformance declared variadic
array with used array variable.

Regards
Pavel Stehule

Attachments:

variadic.2.2.1.difftext/x-patch; name=variadic.2.2.1.diffDownload+524-145
#20Simon Riggs
simon@2ndQuadrant.com
In reply to: Pavel Stehule (#1)
Re: variadic function support

On Mon, 2008-06-23 at 15:13 +0200, Pavel Stehule wrote:

this patch enhance current syntax of CREATE FUNCTION statement. It
allows creating functions with variable number of arguments. This
version is different than last my patches. It doesn't need patching
PL. Basic idea is transformation of real arguments (related to
declared variadic argument) to array. All changes are mostly in
parser.

Something for the TODO.

An added thought with regard to variadic functions:

when we have them, we should be able to parse/transform repeated
operator sequences into a call to a variadic function, if it exists.

e.g. w || x || y || z can be transformed into a call to
concat_variadic(w, x, y, z)

This can then be made to perform better than

concat(concat(concat(w, x), y), z)

which would involve lots of wasted memory copies.

--
Simon Riggs www.2ndQuadrant.com
PostgreSQL Training, Services and Support

#21Pavel Stehule
pavel.stehule@gmail.com
In reply to: Simon Riggs (#20)
#22Jeff Davis
pgsql@j-davis.com
In reply to: Pavel Stehule (#19)
#23Pavel Stehule
pavel.stehule@gmail.com
In reply to: Jeff Davis (#22)
#24Jeff Davis
pgsql@j-davis.com
In reply to: Pavel Stehule (#12)
#25Jeff Davis
pgsql@j-davis.com
In reply to: Pavel Stehule (#23)
#26Jeff Davis
pgsql@j-davis.com
In reply to: Jeff Davis (#24)
#27Pavel Stehule
pavel.stehule@gmail.com
In reply to: Jeff Davis (#24)
#28Pavel Stehule
pavel.stehule@gmail.com
In reply to: Jeff Davis (#25)
#29Tom Lane
tgl@sss.pgh.pa.us
In reply to: Pavel Stehule (#27)
#30Pavel Stehule
pavel.stehule@gmail.com
In reply to: Tom Lane (#29)
#31Pavel Stehule
pavel.stehule@gmail.com
In reply to: Tom Lane (#29)
#32Florian Pflug
fgp@phlo.org
In reply to: Pavel Stehule (#30)
#33Pavel Stehule
pavel.stehule@gmail.com
In reply to: Florian Pflug (#32)
#34Tom Lane
tgl@sss.pgh.pa.us
In reply to: Pavel Stehule (#33)
#35Jeff Davis
pgsql@j-davis.com
In reply to: Tom Lane (#29)
#36Tom Lane
tgl@sss.pgh.pa.us
In reply to: Jeff Davis (#35)
#37Pavel Stehule
pavel.stehule@gmail.com
In reply to: Tom Lane (#34)
#38Tom Lane
tgl@sss.pgh.pa.us
In reply to: Pavel Stehule (#37)
#39Pavel Stehule
pavel.stehule@gmail.com
In reply to: Tom Lane (#38)
#40Tom Lane
tgl@sss.pgh.pa.us
In reply to: Pavel Stehule (#33)
#41Pavel Stehule
pavel.stehule@gmail.com
In reply to: Pavel Stehule (#39)
#42Tom Lane
tgl@sss.pgh.pa.us
In reply to: Pavel Stehule (#41)