Thread: BUG #6774: FOR IN SELECT LOOP ignores ORDER BY

BUG #6774: FOR IN SELECT LOOP ignores ORDER BY

From
boris@folgmann.de
Date:
The following bug has been logged on the website:

Bug reference:      6774
Logged by:          Boris Folgmann
Email address:      boris@folgmann.de
PostgreSQL version: 8.4.12
Operating system:   CentOS 6.3
Description:=20=20=20=20=20=20=20=20

This is an really interesting one!
I've trimmed down the problem so you can simply reproduce it by copy &
paste:

CREATE OR REPLACE FUNCTION ignores_order_by()
RETURNS TABLE(datname VARCHAR) AS $$
DECLARE
        r       RECORD;
BEGIN
        FOR r IN SELECT * FROM pg_database WHERE datallowconn ORDER BY
datname
        LOOP
            datname :=3D r.datname;
            RETURN NEXT;
        END LOOP;
END;
$$ LANGUAGE 'plpgsql';

CREATE OR REPLACE FUNCTION respects_order_by()
RETURNS TABLE(dn VARCHAR) AS $$
DECLARE
        r       RECORD;
BEGIN
        FOR r IN SELECT * FROM pg_database WHERE datallowconn ORDER BY
datname
        LOOP
            dn :=3D r.datname;
            RETURN NEXT;
        END LOOP;
END;
$$ LANGUAGE 'plpgsql';

SELECT * from ignores_order_by();
SELECT * from respects_order_by();

Now compare the different output!
The only difference of the two functions is that the first one uses a
variable with the same name of a column.
This might be a feature and not a bug, but browsing through the
documentation I could not find any documented restrictions on variable names
in this context.

Re: BUG #6774: FOR IN SELECT LOOP ignores ORDER BY

From
hubert depesz lubaczewski
Date:
On Fri, Jul 27, 2012 at 02:56:18PM +0000, boris@folgmann.de wrote:
> This is an really interesting one!
> I've trimmed down the problem so you can simply reproduce it by copy &
> paste:
> The only difference of the two functions is that the first one uses a
> variable with the same name of a column.
> This might be a feature and not a bug, but browsing through the
> documentation I could not find any documented restrictions on variable names
> in this context.

and the variable name is the problem.

generally - order by datname is understood as "order by *variable
datname*". - which is null.

change the select to:
select d.* from pg_database d order by d.datname
and now there is no more problem - because you're no longer using
ambiguous identifier.

Also, check this:
http://www.depesz.com/2009/12/16/waiting-for-8-5-plpgsql-variable-resolution/

Best regards,

depesz

--
The best thing about modern society is how easy it is to avoid contact with it.
                                                             http://depesz.com/

Re: BUG #6774: FOR IN SELECT LOOP ignores ORDER BY

From
Boris Folgmann
Date:
Hi,

hubert depesz lubaczewski schrieb/wrote:
> generally - order by datname is understood as "order by *variable
> datname*". - which is null.

It's clear that it's a shadowing problem. But it's not a "FOR IN EXECUTE"
where a variable makes sense. I mean why is a "ORDER BY variable" valid in
"FOR IN"? In SQL you can't use ORDER BY NULL. If the order by clause is not
correct the whole statement should raise an error.

Tnx,
       Boris

Re: BUG #6774: FOR IN SELECT LOOP ignores ORDER BY

From
Jan Wieck
Date:
On 7/30/2012 5:56 AM, Boris Folgmann wrote:
> Hi,
>
> hubert depesz lubaczewski schrieb/wrote:
>> generally - order by datname is understood as "order by *variable
>> datname*". - which is null.
>
> It's clear that it's a shadowing problem. But it's not a "FOR IN EXECUTE"
> where a variable makes sense. I mean why is a "ORDER BY variable" valid in
> "FOR IN"? In SQL you can't use ORDER BY NULL. If the order by clause is not
> correct the whole statement should raise an error.

Note that PL/pgSQL replaces all local variables inside a query with
$-parameters for the prepared SPI plan. The parser rejects ordering by
non-integer constants, but it does not reject ordering by $-parameters
or constant expressions. (maybe it should). You can for example

     SELECT * FROM something ORDER BY 'foo'||'bar';


Jan

--
Anyone who trades liberty for security deserves neither
liberty nor security. -- Benjamin Franklin

Re: BUG #6774: FOR IN SELECT LOOP ignores ORDER BY

From
Tom Lane
Date:
Jan Wieck <JanWieck@Yahoo.com> writes:
> Note that PL/pgSQL replaces all local variables inside a query with
> $-parameters for the prepared SPI plan. The parser rejects ordering by
> non-integer constants, but it does not reject ordering by $-parameters
> or constant expressions. (maybe it should).

The only real reason it complains about simple constants is that
otherwise people might think "ORDER BY 1" means something different
than what it does mean according to SQL92.  Otherwise, if you want
to sort by a constant, who are we to stop you?

            regards, tom lane