Thread: Functions returning sets

Functions returning sets

From
mlw
Date:
Sorry to gripe here. Don't get me wrong, I think Postgres is amazing, and I
think all you guys do an amazing job. 

Is it just me, or do others agree, functions returning sets need to be able to
be used in a select where equal clause.

select * from table where field = funct_set('bla bla');

Where funct_set returns multiple results. This currently does not work. The
only other option with sets is usage like:

select * from table where field in (select funct_set('bla bla')) ;

Which would be OK if it were able to use an index and preserve the order
returned.

Without the ability to use a set to select multiple objects in a join, it is
dramatically limited in use for a relational database. In fact, I can't think
of many uses for it as is.

Having used Postgres since 1996/1997 I have only a very few gripes, and I think
7.1 is a fantastic effort, but, I think a HUGE amount of applications can not
be done because of this limitation.

What can I do to help get this ability in 7.2? I is VERY important to a project
on which I am working.


Re: Functions returning sets

From
Stephan Szabo
Date:
(Machine couldn't find mx record for mohawksoft, replying only
to list)

On Sat, 19 May 2001, mlw wrote:

> Sorry to gripe here. Don't get me wrong, I think Postgres is amazing, and I
> think all you guys do an amazing job. 
> 
> Is it just me, or do others agree, functions returning sets need to be able to
> be used in a select where equal clause.
>
> select * from table where field = funct_set('bla bla');

I think what we should probably do is make IN better and use that or then
support =ANY(=SOME)/=ALL on such things.  I think =ANY would be easy
since IN is defined in terms of it in the spec.

I personally don't like the idea of value = set being value in set any
more than value = array being value in array.



Re: Functions returning sets

From
mlw
Date:
Stephan Szabo wrote:
> 
> (Machine couldn't find mx record for mohawksoft, replying only
> to list)
> 
> On Sat, 19 May 2001, mlw wrote:
> 
> > Sorry to gripe here. Don't get me wrong, I think Postgres is amazing, and I
> > think all you guys do an amazing job.
> >
> > Is it just me, or do others agree, functions returning sets need to be able to
> > be used in a select where equal clause.
> >
> > select * from table where field = funct_set('bla bla');

I don't understand your reasoning.  Look at the syntax:

select * from foo where bar = function(...);

If function() returns one value, then only one will be returned and the
relation features of postgres can be used, as in "select * from foo, this where
foo.bar = function() and foo.bar = this.that"

If function() can return multiple values, should it not follow that multiple
values should be selected? 

In the example where one result is returned, that makes sense. Why does the
example of multiple results being returned no longer make sense?

It is a point of extreme frustration to me that I can't do this easily. Lacking
this ability makes Postgres almost impossible to implement a search engine
correctly. I know it is selfish to feel this way, but I am positive my
frustration is indicative of others out there trying to use Postgres for
certain applications.  I bet a huge number of developers  feel the same way,
but try a few quick tests and give up on Postgres all together, without saying
a word. What good are multiple results in a relational environment if one can
not use them as relations?


RE: Re: Functions returning sets

From
Mike Mascari
Date:
I see Tom Lane implemented the SQL92 feature of using subselects in 
FROM clauses:

CREATE TABLE foo (
key integer not null,
value text);

SELECT * FROM (SELECT * FROM foo) AS bar
WHERE bar.key = 1;

Perhaps this is how functions returning sets should operate:

SELECT titles.* FROM titles, (SELECT funct_set('blah blah')) AS bar
WHERE titles.title = bar.title;

FWIW,

Mike Mascari
mascarm@mascari.com

-----Original Message-----
From:    mlw [SMTP:markw@mohawksoft.com]
Sent:    Saturday, May 19, 2001 5:42 PM
To:    Stephan Szabo
Cc:    Hackers List
Subject:    [HACKERS] Re: Functions returning sets

Stephan Szabo wrote:
>
> (Machine couldn't find mx record for mohawksoft, replying only
> to list)
>
> On Sat, 19 May 2001, mlw wrote:
>
> > Sorry to gripe here. Don't get me wrong, I think Postgres is 
amazing, and I
> > think all you guys do an amazing job.
> >
> > Is it just me, or do others agree, functions returning sets need 
to be able to
> > be used in a select where equal clause.
> >
> > select * from table where field = funct_set('bla bla');

I don't understand your reasoning.  Look at the syntax:

select * from foo where bar = function(...);

If function() returns one value, then only one will be returned and 
the
relation features of postgres can be used, as in "select * from foo, 
this where
foo.bar = function() and foo.bar = this.that"

If function() can return multiple values, should it not follow that 
multiple
values should be selected?

In the example where one result is returned, that makes sense. Why 
does the
example of multiple results being returned no longer make sense?

It is a point of extreme frustration to me that I can't do this 
easily. Lacking
this ability makes Postgres almost impossible to implement a search 
engine
correctly. I know it is selfish to feel this way, but I am positive 
my
frustration is indicative of others out there trying to use Postgres 
for
certain applications.  I bet a huge number of developers  feel the 
same way,
but try a few quick tests and give up on Postgres all together, 
without saying
a word. What good are multiple results in a relational environment if 
one can
not use them as relations?



Re: Functions returning sets

From
Don Baccus
Date:
At 02:08 PM 5/19/01 -0700, Stephan Szabo wrote:
>
>(Machine couldn't find mx record for mohawksoft, replying only
>to list)
>
>On Sat, 19 May 2001, mlw wrote:
>
>> Sorry to gripe here. Don't get me wrong, I think Postgres is amazing, and I
>> think all you guys do an amazing job. 
>> 
>> Is it just me, or do others agree, functions returning sets need to be able to
>> be used in a select where equal clause.
>>
>> select * from table where field = funct_set('bla bla');
>
>I think what we should probably do is make IN better...

IN is the right operator.  "field = [set of rows]" isn't SQL92 and doesn't
really make sense.   It's the equivalent of:

select * from table where field = (select some_column from some_other_table)

If the subselect returns a single row it will work, if it returns multiple
rows you need to use IN.  That's just how SQL92 is defined.

I'd assume that a function returning a single column and single row will
work just as the subselect does, but there's no reason expect it to work
if more than one row is returned.

What's so hard about writing "IN" rather than "=" ???



- Don Baccus, Portland OR <dhogaza@pacifier.com> Nature photos, on-line guides, Pacific Northwest Rare Bird Alert
Serviceand other goodies at http://donb.photo.net.
 


Re: Re: Functions returning sets

From
"Joe Conway"
Date:
> I see Tom Lane implemented the SQL92 feature of using subselects in
> FROM clauses:
>
> CREATE TABLE foo (
> key integer not null,
> value text);
>
> SELECT * FROM (SELECT * FROM foo) AS bar
> WHERE bar.key = 1;
>
> Perhaps this is how functions returning sets should operate:
>
> SELECT titles.* FROM titles, (SELECT funct_set('blah blah')) AS bar
> WHERE titles.title = bar.title;
>

This is exactly what I was thinking. To take it one step further, then you
could define a view as:

CREATE VIEW vw_funct_set as (SELECT funct_set('blah blah'));

Then the statement above might look like:

SELECT titles.* FROM titles, vw_funct_set AS bar WHERE titles.title =
bar.title;

IMHO this seems the most natural way to do what you have proposed.

-- Joe



Re: Functions returning sets

From
Tom Lane
Date:
Don Baccus <dhogaza@pacifier.com> writes:
> What's so hard about writing "IN" rather than "=" ???

Even more to the point, if we did adopt such a (crazy IMHO)
interpretation of '=', what makes anyone think that it'd be
any more efficient than IN?

AFAICT, mlw is hoping that redefining '=' would magically avoid the
performance problems with IN, but my bet is it'd be just the same.

What we need to do is teach the system how to handle WHERE ... IN ...
as a form of join.  Changing semantics of operators isn't necessary
nor helpful.
        regards, tom lane


Re: Functions returning sets

From
Tom Lane
Date:
Stephan Szabo <sszabo@megazone23.bigpanda.com> writes:
> I think what we should probably do is make IN better and use that or then
> support =ANY(=SOME)/=ALL on such things.  I think =ANY would be easy
> since IN is defined in terms of it in the spec.

And in our code too ;-).  ANY/ALL have been there for awhile.
        regards, tom lane


Re: Functions returning sets

From
Don Baccus
Date:
At 08:44 PM 5/19/01 -0400, Tom Lane wrote:
>Don Baccus <dhogaza@pacifier.com> writes:
>> What's so hard about writing "IN" rather than "=" ???
>
>Even more to the point, if we did adopt such a (crazy IMHO)
>interpretation of '=', what makes anyone think that it'd be
>any more efficient than IN?

I was going to mention this, but stuck to the old letter-to-the-editor
rule of one point per note. :)

>AFAICT, mlw is hoping that redefining '=' would magically avoid the
>performance problems with IN, but my bet is it'd be just the same.

Or that it would actually be a join operator???  Wasn't clear to me
exactly what he was expecting.

>What we need to do is teach the system how to handle WHERE ... IN ...
>as a form of join.

Yes.

BTW Oracle has a 1000-element limit on the number of values in an
"IN" set.  This limits its generality as it applies to subselects
as well as lists of constants.  It seems that PG isn't the only
RDMBS that has problems with getting "IN" implemented perfectly.



- Don Baccus, Portland OR <dhogaza@pacifier.com> Nature photos, on-line guides, Pacific Northwest Rare Bird Alert
Serviceand other goodies at http://donb.photo.net.
 


Re: Functions returning sets

From
mlw
Date:
Tom Lane wrote:
> 
> Don Baccus <dhogaza@pacifier.com> writes:
> > What's so hard about writing "IN" rather than "=" ???
> 
> Even more to the point, if we did adopt such a (crazy IMHO)
> interpretation of '=', what makes anyone think that it'd be
> any more efficient than IN?
> 
> AFAICT, mlw is hoping that redefining '=' would magically avoid the
> performance problems with IN, but my bet is it'd be just the same.
> 
> What we need to do is teach the system how to handle WHERE ... IN ...
> as a form of join.  Changing semantics of operators isn't necessary
> nor helpful.

I will defer, of course, to your interpretation of '=', but I still think it
(if implemented efficiently) could be cool. However, I hang my head in shame
that I didn't see this syntax:

select table.* from table, (select function() as field) as result where
table.field = result.field;

It seems to be pretty efficient, and satisfies the main criteria that I needed,
which was a full text search could be used on select with no external
programming language.

Currently my system can't be used without an external programming language, and
this is a huge, if awkward solution. Thanks all.


Re: Functions returning sets

From
Tom Lane
Date:
Don Baccus <dhogaza@pacifier.com> writes:
> BTW Oracle has a 1000-element limit on the number of values in an
> "IN" set.

Yeah?  What happens when you get past that?
        regards, tom lane


Re: Re: Functions returning sets

From
Oleg Bartunov
Date:
I think you probably could use contrib/intarray if you redesign
your scheme.
Oleg

On Sat, 19 May 2001, mlw wrote:

> Tom Lane wrote:
> >
> > Don Baccus <dhogaza@pacifier.com> writes:
> > > What's so hard about writing "IN" rather than "=" ???
> >
> > Even more to the point, if we did adopt such a (crazy IMHO)
> > interpretation of '=', what makes anyone think that it'd be
> > any more efficient than IN?
> >
> > AFAICT, mlw is hoping that redefining '=' would magically avoid the
> > performance problems with IN, but my bet is it'd be just the same.
> >
> > What we need to do is teach the system how to handle WHERE ... IN ...
> > as a form of join.  Changing semantics of operators isn't necessary
> > nor helpful.
>
> I will defer, of course, to your interpretation of '=', but I still think it
> (if implemented efficiently) could be cool. However, I hang my head in shame
> that I didn't see this syntax:
>
> select table.* from table, (select function() as field) as result where
> table.field = result.field;
>
> It seems to be pretty efficient, and satisfies the main criteria that I needed,
> which was a full text search could be used on select with no external
> programming language.
>
> Currently my system can't be used without an external programming language, and
> this is a huge, if awkward solution. Thanks all.
>
> ---------------------------(end of broadcast)---------------------------
> TIP 6: Have you searched our list archives?
>
> http://www.postgresql.org/search.mpl
>
Regards,    Oleg
_____________________________________________________________
Oleg Bartunov, sci.researcher, hostmaster of AstroNet,
Sternberg Astronomical Institute, Moscow University (Russia)
Internet: oleg@sai.msu.su, http://www.sai.msu.su/~megera/
phone: +007(095)939-16-83, +007(095)939-23-83



Re: Re: Functions returning sets

From
Hannu Krosing
Date:
mlw wrote:
> 
> Stephan Szabo wrote:
> >
> > (Machine couldn't find mx record for mohawksoft, replying only
> > to list)
> >
> > On Sat, 19 May 2001, mlw wrote:
> >
> > > Sorry to gripe here. Don't get me wrong, I think Postgres is amazing, and I
> > > think all you guys do an amazing job.
> > >
> > > Is it just me, or do others agree, functions returning sets need to be able to
> > > be used in a select where equal clause.
> > >
> > > select * from table where field = funct_set('bla bla');
> 
> I don't understand your reasoning.  Look at the syntax:
> 
> select * from foo where bar = function(...);
> 
> If function() returns one value, then only one will be returned and the
> relation features of postgres can be used, as in "select * from foo, this where
> foo.bar = function() and foo.bar = this.that"
> 
> If function() can return multiple values, should it not follow that multiple
> values should be selected?

of course not! if function() can return (i.e. returns) as set then bar
must be of 
type SET too and only rows that are = (in whatever sense currently
defined) should
be returned

---------------
Hannu


Re: Functions returning sets

From
Don Baccus
Date:
At 12:31 AM 5/20/01 -0400, Tom Lane wrote:
>Don Baccus <dhogaza@pacifier.com> writes:
>> BTW Oracle has a 1000-element limit on the number of values in an
>> "IN" set.
>
>Yeah?  What happens when you get past that?

My understanding is that it gives you an error, though I've never tried
it myself.



- Don Baccus, Portland OR <dhogaza@pacifier.com> Nature photos, on-line guides, Pacific Northwest Rare Bird Alert
Serviceand other goodies at http://donb.photo.net.
 


Re: Functions returning sets

From
Matthew Kirkwood
Date:
On Sun, 20 May 2001, Don Baccus wrote:

> >> BTW Oracle has a 1000-element limit on the number of values in an
> >> "IN" set.
> >
> >Yeah?  What happens when you get past that?
>
> My understanding is that it gives you an error, though I've never
> tried it myself.

It does.

Matthew.



Re: Functions returning sets

From
Stephan Szabo
Date:
On Sat, 19 May 2001, mlw wrote:

> Stephan Szabo wrote:
> > 
> > (Machine couldn't find mx record for mohawksoft, replying only
> > to list)
> > 
> > On Sat, 19 May 2001, mlw wrote:
> > 
> > > Sorry to gripe here. Don't get me wrong, I think Postgres is amazing, and I
> > > think all you guys do an amazing job.
> > >
> > > Is it just me, or do others agree, functions returning sets need to be able to
> > > be used in a select where equal clause.
> > >
> > > select * from table where field = funct_set('bla bla');
> 
> I don't understand your reasoning.  Look at the syntax:
> 
> select * from foo where bar = function(...);
> 
> If function() returns one value, then only one will be returned and the
> relation features of postgres can be used, as in "select * from foo, this where
> foo.bar = function() and foo.bar = this.that"
> 
> If function() can return multiple values, should it not follow that multiple
> values should be selected? 

What does select * from foo where bar=(select value from foo2) mean when
the second returns more than one row.  IIRC, sql says that's an error.
I don't see why functions returning sets would be different than a
subquery.  That's what =ANY, =ALL, and IN are for.  I don't see what the
difference between doing this with =s and making IN work better really is.



Re: Functions returning sets

From
Stephan Szabo
Date:
On Sat, 19 May 2001, Tom Lane wrote:

> Stephan Szabo <sszabo@megazone23.bigpanda.com> writes:
> > I think what we should probably do is make IN better and use that or then
> > support =ANY(=SOME)/=ALL on such things.  I think =ANY would be easy
> > since IN is defined in terms of it in the spec.
> 
> And in our code too ;-).  ANY/ALL have been there for awhile.

:) Well that makes it easier anyway.  I do agree with the point that at
some point IN needs to be smarter.  Can the IN always get written as a
join and is it always better to do so?




Re: Functions returning sets

From
Don Baccus
Date:
At 10:55 AM 5/20/01 -0700, Stephan Szabo wrote:
> Can the IN always get written as a
>join and is it always better to do so?

Nope:

openacs4=# select 1 in (1,2,3);?column? 
----------t
(1 row)

You might also do something like

"select count(*) from foo where foo.state in ('rejected', 'banned');"

A better question, I guess, is if it is always better to write
it as a join if the left hand operand is a table column and
the right hand operand a rowset.





- Don Baccus, Portland OR <dhogaza@pacifier.com> Nature photos, on-line guides, Pacific Northwest Rare Bird Alert
Serviceand other goodies at http://donb.photo.net.
 


Re: Functions returning sets

From
Stephan Szabo
Date:
On Sun, 20 May 2001, Don Baccus wrote:

> At 10:55 AM 5/20/01 -0700, Stephan Szabo wrote:
> > Can the IN always get written as a
> >join and is it always better to do so?
> 
> Nope:
> ...
> A better question, I guess, is if it is always better to write
> it as a join if the left hand operand is a table column and
> the right hand operand a rowset.

Well I was assuming we were talking about the subquery case
in general :)

It might be a problem with subqueries with set value functions
and parameters passed down from the outer tables:
select * from blah whereblah.val1 in  (select count(*) from blah2 where blah2.val2=blah.val2   group by blah2.val3);



RE: Re: Functions returning sets

From
mordicus
Date:
Why not like Interbase ?

when you define a procedure in Interbase, you have the 'suspend' 
instruction, 
it suspend execution of the stored procedure and returns variables, then 
come back to the procedure.

select * from myfunc('ba ba');
select mycol from myfunc('dada');

escuse my poor english :)


Mike Mascari wrote:

> I see Tom Lane implemented the SQL92 feature of using subselects in
> FROM clauses:
> 
> CREATE TABLE foo (
> key integer not null,
> value text);
> 
> SELECT * FROM (SELECT * FROM foo) AS bar
> WHERE bar.key = 1;
> 
> Perhaps this is how functions returning sets should operate:
> 
> SELECT titles.* FROM titles, (SELECT funct_set('blah blah')) AS bar
> WHERE titles.title = bar.title;
> 
> FWIW,
> 
> Mike Mascari
> mascarm@mascari.com



RE: Re: Functions returning sets

From
mordicus
Date:
Why not like Interbase ?

when you define a procedure in Interbase, you a the 'suspend' instruction, 
it suspend execution of the stored procedure and returns variables, then 
come back to the procedure.

select * from myfunc('ba ba');
select mycol from myfunc('dada');

escuse my poor english :)

....
Mike Mascari wrote:

> I see Tom Lane implemented the SQL92 feature of using subselects in
> FROM clauses:
> 
> CREATE TABLE foo (
> key integer not null,
> value text);
> 
> SELECT * FROM (SELECT * FROM foo) AS bar
> WHERE bar.key = 1;
> 
> Perhaps this is how functions returning sets should operate:
> 
> SELECT titles.* FROM titles, (SELECT funct_set('blah blah')) AS bar
> WHERE titles.title = bar.title;
> 
> FWIW,
> 
> Mike Mascari
> mascarm@mascari.com