ORDER BY with EXCEPT?

Started by David E. Wheeleralmost 17 years ago6 messages
#1David E. Wheeler
david@kineticode.com

Howdy,

I was just updating a function in pgTAP that, given a schema name and
an array of function names, returns a set of those function names that
are not in the named schema. I got it working with a subquery, and
David Fetter suggested that I try an EXCEPT query instead. The only
problem is that it doesn't like my ORDER BY clause. The function is:

CREATE OR REPLACE FUNCTION mytest(NAME, NAME[]) RETURNS setof text AS
$$
SELECT quote_ident($2[i])
FROM generate_series(1, array_upper($2, 1)) AS s(i)
EXCEPT
SELECT quote_ident(p.proname)
FROM pg_catalog.pg_proc p
JOIN pg_catalog.pg_namespace n
ON p.pronamespace = n.oid
AND quote_ident(n.nspname) = quote_ident($1)
ORDER BY s.i
$$ LANGUAGE SQL;

When I run this, PostgreSQL 8.3 tells me:

ERROR: missing FROM-clause entry for table "s"
LINE 10: ORDER BY s.i

Um, really" Have I not put the ORDER BY clause in the right place? Is
this a bug?

Thanks,

David

#2Jeff Davis
pgsql@j-davis.com
In reply to: David E. Wheeler (#1)
Re: ORDER BY with EXCEPT?

On Thu, 2009-02-19 at 17:13 -0800, David E. Wheeler wrote:

CREATE OR REPLACE FUNCTION mytest(NAME, NAME[]) RETURNS setof text AS
$$
SELECT quote_ident($2[i])
FROM generate_series(1, array_upper($2, 1)) AS s(i)
EXCEPT
SELECT quote_ident(p.proname)
FROM pg_catalog.pg_proc p
JOIN pg_catalog.pg_namespace n
ON p.pronamespace = n.oid
AND quote_ident(n.nspname) = quote_ident($1)
ORDER BY s.i
$$ LANGUAGE SQL;

You can make it work by naming the first quote_ident like
"quote_ident($2[i]) AS foo" and then doing ORDER BY foo.

It seems a little strange to me, too, but I assume that it's SQL
standard behavior.

Regards,
Jeff Davis

#3Andrew Dunstan
andrew@dunslane.net
In reply to: David E. Wheeler (#1)
Re: ORDER BY with EXCEPT?

David E. Wheeler wrote:

Howdy,

I was just updating a function in pgTAP that, given a schema name and
an array of function names, returns a set of those function names that
are not in the named schema. I got it working with a subquery, and
David Fetter suggested that I try an EXCEPT query instead. The only
problem is that it doesn't like my ORDER BY clause. The function is:

CREATE OR REPLACE FUNCTION mytest(NAME, NAME[]) RETURNS setof text AS $$
SELECT quote_ident($2[i])
FROM generate_series(1, array_upper($2, 1)) AS s(i)
EXCEPT
SELECT quote_ident(p.proname)
FROM pg_catalog.pg_proc p
JOIN pg_catalog.pg_namespace n
ON p.pronamespace = n.oid
AND quote_ident(n.nspname) = quote_ident($1)
ORDER BY s.i
$$ LANGUAGE SQL;

When I run this, PostgreSQL 8.3 tells me:

ERROR: missing FROM-clause entry for table "s"
LINE 10: ORDER BY s.i

Um, really" Have I not put the ORDER BY clause in the right place? Is
this a bug?

The docs say
<http://www.postgresql.org/docs/current/static/sql-select.html#SQL-ORDERBY&gt;:

"A limitation of this feature is that an ORDER BY clause applying to the
result of a UNION, INTERSECT, or EXCEPT clause can only specify an
output column name or number, not an expression."

Why not just say "order by 1" ?

cheers

andrew

#4David E. Wheeler
david@kineticode.com
In reply to: Andrew Dunstan (#3)
Re: ORDER BY with EXCEPT?

On Feb 19, 2009, at 5:45 PM, Andrew Dunstan wrote:

"A limitation of this feature is that an ORDER BY clause applying to
the result of a UNION, INTERSECT, or EXCEPT clause can only specify
an output column name or number, not an expression."

Why not just say "order by 1" ?

Well, in this case, I wanted the order to be the same as in the array
that was passed.

At any rate, your quotation of this documentation that I obviously
missed answers my question. In the meantime, I got a different version
with a LEFT JOIN to do what I want, so I don't need the EXCEPT at all.
I just posted here because it looked like a bug. And though it's
clearly not, since it's documented, it is kinda weird…

Thanks,

David

#5Andrew Dunstan
andrew@dunslane.net
In reply to: David E. Wheeler (#4)
Re: ORDER BY with EXCEPT?

David E. Wheeler wrote:

On Feb 19, 2009, at 5:45 PM, Andrew Dunstan wrote:

"A limitation of this feature is that an ORDER BY clause applying to
the result of a UNION, INTERSECT, or EXCEPT clause can only specify
an output column name or number, not an expression."

Why not just say "order by 1" ?

Well, in this case, I wanted the order to be the same as in the array
that was passed.

Yeah. you can do it like this:

select foo from (
SELECT quote_ident($2[i]) as foo, i
FROM generate_series(1, array_upper($2, 1)) AS s(i)
EXCEPT
SELECT quote_ident(p.proname)
FROM pg_catalog.pg_proc p
JOIN pg_catalog.pg_namespace n
ON p.pronamespace = n.oid
AND quote_ident(n.nspname) = quote_ident($1)
ORDER BY i ) x;

At any rate, your quotation of this documentation that I obviously
missed answers my question. In the meantime, I got a different version
with a LEFT JOIN to do what I want, so I don't need the EXCEPT at all.
I just posted here because it looked like a bug. And though it's
clearly not, since it's documented, it is kinda weird�

There are many odd corners, unfortunately.

cheers

andrew

#6Andrew Dunstan
andrew@dunslane.net
In reply to: Andrew Dunstan (#5)
Re: ORDER BY with EXCEPT?

I wrote:

select foo from (
SELECT quote_ident($2[i]) as foo, i
FROM generate_series(1, array_upper($2, 1)) AS s(i)
EXCEPT
SELECT quote_ident(p.proname)
FROM pg_catalog.pg_proc p
JOIN pg_catalog.pg_namespace n
ON p.pronamespace = n.oid
AND quote_ident(n.nspname) = quote_ident($1)
ORDER BY i ) x;

This won't work of course.

brain malfunctioning again :-(

sorry for noise.

andrew