Thread: generic return for functions

generic return for functions

From
"Danny Su"
Date:
Hi, this is my first time using mailing list.  Someone over at tek-tips 
suggested that I try here to see if someone can help me.

I am currently converting everything from SQL Server to PostgreSQL.  This is 
for an application that is going to support Oracle, SQL Server and 
PostgreSQL at the same time.  I have done a lot of the conversion already 
but I am stuck on functions that returns parts of views or tables.

In SQL Server, you can create User Defined functions that returns type 
"TABLE"... so then you can simply return the result of a select statement... 
(e.g. return select * from mytable)
The problem is that I don't know if there is a way to do this in PostgreSQL.
My functions and stored procedures in SQL Server involves select statement 
that gets columns from few views and tables.
I know I can create my own data type with all the columns that are going to 
be returned, or get my function to return a type "record"... however, I 
don't like both of these methods since some of my functions involves 
returning a select statement using inner join and all that stuff... some 
have like 30 columns

There seems to be another way to use refcursor but my application is in 
ColdFusion... refcursor doesn't seem to work with it.

I know "returns setof record" and "returns setof my_own_datatype" work, but 
I would like to know if there is a better way? Something that's like 
"returns setof record" but without having to define all the columns when I 
call the function? {i.e. without the need to do: select * from myfunction() 
as (column1 type1, column2...);}

If there is such method? It will allow me to maintain the application much 
easier and makes the conversion task much easier :)

Thanks.
/Danny

_________________________________________________________________
Tired of spam? Get advanced junk mail protection with MSN 8.  
http://join.msn.com/?page=features/junkmail



Re: generic return for functions

From
Avi Schwartz
Date:
I am afraid you are in exactly the same boat I am in.  Coldfusion does 
not recognize the refcursor and as far as I know, currently the only 
way to return a result set that CF can read is to return a setof which 
requires you to return a user defined data type or a record.  Another 
thing that causes me some minor grief is the fact that currently you 
cannot have default values to function parameters, a feature we use a 
lot.

Avi

On Saturday, May 31, 2003, at 23:02 America/Chicago, Danny Su wrote:

> I am currently converting everything from SQL Server to PostgreSQL.  
> This is for an application that is going to support Oracle, SQL Server 
> and PostgreSQL at the same time.  I have done a lot of the conversion 
> already but I am stuck on functions that returns parts of views or 
> tables.
>
> In SQL Server, you can create User Defined functions that returns type 
> "TABLE"... so then you can simply return the result of a select 
> statement... (e.g. return select * from mytable)
> The problem is that I don't know if there is a way to do this in 
> PostgreSQL.
> My functions and stored procedures in SQL Server involves select 
> statement that gets columns from few views and tables.
> I know I can create my own data type with all the columns that are 
> going to be returned, or get my function to return a type "record"... 
> however, I don't like both of these methods since some of my functions 
> involves returning a select statement using inner join and all that 
> stuff... some have like 30 columns
>
> There seems to be another way to use refcursor but my application is 
> in ColdFusion... refcursor doesn't seem to work with it.
>
> I know "returns setof record" and "returns setof my_own_datatype" 
> work, but I would like to know if there is a better way? Something 
> that's like "returns setof record" but without having to define all 
> the columns when I call the function? {i.e. without the need to do: 
> select * from myfunction() as (column1 type1, column2...);}
>
> If there is such method? It will allow me to maintain the application 
> much easier and makes the conversion task much easier :)
-- 
Avi Schwartz
avi@CFFtechnologies.com



Re: generic return for functions

From
Joe Conway
Date:
Danny Su wrote:
> I am currently converting everything from SQL Server to PostgreSQL.  
> This is for an application that is going to support Oracle, SQL Server 
> and PostgreSQL at the same time.  I have done a lot of the conversion 
> already but I am stuck on functions that returns parts of views or tables.
> 
[...snip description of SQL Server 2000 table-valued UDFs...]
> 
> I know "returns setof record" and "returns setof my_own_datatype" work, 
> but I would like to know if there is a better way? Something that's like 
> "returns setof record" but without having to define all the columns when 
> I call the function? {i.e. without the need to do: select * from 
> myfunction() as (column1 type1, column2...);}
> 
> If there is such method? It will allow me to maintain the application 
> much easier and makes the conversion task much easier :)
> 

Sorry -- the answer is no. But I don't think Oracle will support what 
you want either.

Joe



Re: generic return for functions

From
Rod Taylor
Date:
> thing that causes me some minor grief is the fact that currently you
> cannot have default values to function parameters, a feature we use a
> lot.

The default value is used when the parameter is NULL or unprovided?

fn(integer, integer, integer default 32)

select fn(integer, integer); <- Third argument would be '32'?


When PostgreSQL gets named parameters the above probably makes sense to
add.

A TODO item?
--
Rod Taylor <rbt@rbt.ca>

PGP Key: http://www.rbt.ca/rbtpub.asc

Re: generic return for functions

From
Avi Schwartz
Date:
Exactly.  It is used with named parameters when the parameter is not 
provided.

Avi

On Sunday, Jun 1, 2003, at 07:21 America/Chicago, Rod Taylor wrote:

>> thing that causes me some minor grief is the fact that currently you
>> cannot have default values to function parameters, a feature we use a
>> lot.
>
> The default value is used when the parameter is NULL or unprovided?
>
> fn(integer, integer, integer default 32)
>
> select fn(integer, integer); <- Third argument would be '32'?
>
>
> When PostgreSQL gets named parameters the above probably makes sense to
> add.
>
> A TODO item?
-- 
Avi Schwartz
avi@CFFtechnologies.com



Re: generic return for functions

From
Tom Lane
Date:
Rod Taylor <rbt@rbt.ca> writes:
>> thing that causes me some minor grief is the fact that currently you=20
>> cannot have default values to function parameters, a feature we use a=20
>> lot.

> fn(integer, integer, integer default 32)
> select fn(integer, integer); <- Third argument would be '32'?
> When PostgreSQL gets named parameters the above probably makes sense to
> add.

> A TODO item?

That isn't ever going to happen.  We have enough difficulty resolving
overloaded functions as it is.  If we couldn't even be sure how many
arguments there were supposed to be, it'd become completely intractable.

You can however achieve similar effects at the user level by adding
auxiliary functions: declare fn(int,int) as a one-line SQL function
that calls fn($1, $2, 32).
        regards, tom lane


Re: generic return for functions

From
Avi Schwartz
Date:
On Sunday, Jun 1, 2003, at 10:46 America/Chicago, Tom Lane wrote:

> Rod Taylor <rbt@rbt.ca> writes:
>>> thing that causes me some minor grief is the fact that currently 
>>> you=20
>>> cannot have default values to function parameters, a feature we use 
>>> a=20
>>> lot.
>
>> fn(integer, integer, integer default 32)
>> select fn(integer, integer); <- Third argument would be '32'?
>> When PostgreSQL gets named parameters the above probably makes sense 
>> to
>> add.
>
>> A TODO item?
>
> That isn't ever going to happen.  We have enough difficulty resolving
> overloaded functions as it is.  If we couldn't even be sure how many
> arguments there were supposed to be, it'd become completely 
> intractable.
>
> You can however achieve similar effects at the user level by adding
> auxiliary functions: declare fn(int,int) as a one-line SQL function
> that calls fn($1, $2, 32).
>
>             regards, tom lane

I understand why it will not be implemented with overloaded functions.  
Is there a possibility to allow this only for functions that are not 
overloaded?  The SQL function solution is really not going to help in 
my case since the function builds a select statement dynamically based 
on which parameters have a non-null value.  The number of parameters is 
something like 12 or 13 and the control on which parameters are set is 
determined by a complex combination of program logic and user 
selections.  What I did to solve this problem was to force all 
variables to be initialized to null and then set the non-null ones 
before the call to the function.

On another note, somewhat related, when we started looking at a 
replacement to SQL Server 7, I looked at SAPDB, MySQL and now 
PostgreSQL.  MySQL lost immediately since the current version is 
missing a lot of functionality we were looking for.  I was not 
impressed by SAPDB's performance, their documentation is extremely hard 
to follow and I found the database very hard to manage.  So far 
PostgreSQL seems to be the best choice for us.  I am yet to find a show 
stopper and the speed is fantastic.  I didn't do extensive comparisons 
yet and I don't have hard numbers, but from what I have seen so far, 
PostgreSQL 7.3.2 is at least as fast as SQL Server 7 in real life 
situations (Of course count(*) is still much faster in SQL Server for 
very large tables (some of our tables are > 5M rows) :-) .  What makes 
it more impressive is the fact that SS runs on a 4 CPU machine with 2 
GB of memory while PostgreSQL on a single CPU machine with 384M memory 
running SuSE 8.2.  In the near future I will be moving the PostgreSQL 
database to a similar configuration as SS.  It will be interested to 
compare them then.

To PostgreSQL developers, thank you for a great product!

Avi
-- 
Avi Schwartz
avi@CFFtechnologies.com



Re: generic return for functions

From
Josh Berkus
Date:
Avi,

> I understand why it will not be implemented with overloaded functions.
> Is there a possibility to allow this only for functions that are not
> overloaded?  

Unfortunately, no.  There's simply no way for the database to tell the 
difference between a function call relying on defaults, and one with the 
wrong parameters.  SQL Server's approach with defaults works *because* SQL 
Server does not support overloaded procedures.

> The SQL function solution is really not going to help in
> my case since the function builds a select statement dynamically based
> on which parameters have a non-null value.  The number of parameters is
> something like 12 or 13 and the control on which parameters are set is
> determined by a complex combination of program logic and user
> selections.  What I did to solve this problem was to force all
> variables to be initialized to null and then set the non-null ones
> before the call to the function.

This sounds like a good solution to me.

BTW, named parameters for PostgreSQL Functions are on the to-do list, but I 
don't think anyone is currently working on them.

> very large tables (some of our tables are > 5M rows) :-) .  What makes
> it more impressive is the fact that SS runs on a 4 CPU machine with 2
> GB of memory while PostgreSQL on a single CPU machine with 384M memory
> running SuSE 8.2.  In the near future I will be moving the PostgreSQL
> database to a similar configuration as SS.  It will be interested to
> compare them then.

That's a very nice testimonial!  Thanks.

BTW, you will probably wish to join the PGSQL-Performance mailing list to make 
sure that you can tune your PostgreSQL database properly.

-- 
Josh Berkus
Aglio Database Solutions
San Francisco