wrong optimization ( postgres 8.0.3 )

Started by Gaetano Mendolaover 20 years ago3 messageshackers
Jump to latest
#1Gaetano Mendola
mendola@bigfoot.com

Hi all,
take a look at this simple function and view:

CREATE OR REPLACE FUNCTION sp_connected_test ( INTEGER )
RETURNS BOOLEAN AS'
DECLARE
a_id_user ALIAS FOR $1;
BEGIN
PERFORM *
FROM v_current_connection
WHERE id_user = a_id_user;

IF NOT FOUND THEN
RETURN FALSE;
END IF;

RETURN TRUE;

END;
' LANGUAGE 'plpgsql';

CREATE VIEW v_current_connection_test
AS SELECT ul.id_user, cc.connected
FROM current_connection cc,
user_login ul
WHERE cc.id_user = ul.id_user AND
connected = TRUE;

SELECT * FROM v_current_connection_test WHERE sp_connected_test(id_user) = FALSE;

this line shall produce no row, but randomly does.

If I put a RAISE NOTICE before RETURN NULL with the id_user I notice that
the function is called on records present on user_login but discarged because
the join with current_connectin have connected = FALSE!

I can work_around the problem rewriting the view:

CREATE VIEW v_current_connection_test
AS SELECT cc.id_user, cc.connected
FROM current_connection cc,
user_login ul
WHERE cc.id_user = ul.id_user AND
connected = TRUE;

Regards
Gaetano Mendola

#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: Gaetano Mendola (#1)
Re: wrong optimization ( postgres 8.0.3 )

Gaetano Mendola <mendola@bigfoot.com> writes:

What I'm experiencing is a problem ( I upgraded today from
7.4.x to 8.0.3 ) that I explain here:

The following function just return how many records there
are inside the view v_current_connection

CREATE OR REPLACE FUNCTION sp_count ( )
RETURNS INTEGER AS'
DECLARE
c INTEGER;
BEGIN
SELECT count(*) INTO c FROM v_current_connection;
RETURN c;
END;
' LANGUAGE 'plpgsql';

I have the following select

# select count(*), sp_count() from v_current_connection;
count | sp_count
- -------+----------
977 | 978

as you can see the two count are returning different record
numbers ( in meant time other transactions are updating tables
behind the view v_current_connection ).

This isn't surprising at all, if other transactions are actively
changing the table. See the release notes for 8.0:

: Observe the following incompatibilities:
:
: In READ COMMITTED serialization mode, volatile functions now see
: the results of concurrent transactions committed up to the
: beginning of each statement within the function, rather than up to
: the beginning of the interactive command that called the function.
:
: Functions declared STABLE or IMMUTABLE always use the snapshot of
: the calling query, and therefore do not see the effects of actions
: taken after the calling query starts, whether in their own
: transaction or other transactions. Such a function must be
: read-only, too, meaning that it cannot use any SQL commands other
: than SELECT.

If you want this function to see the same snapshot as the calling query
sees, declare it STABLE.

regards, tom lane

#3Gaetano Mendola
mendola@bigfoot.com
In reply to: Tom Lane (#2)
Re: wrong optimization ( postgres 8.0.3 )

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Tom Lane wrote:

Gaetano Mendola <mendola@bigfoot.com> writes:

What I'm experiencing is a problem ( I upgraded today from
7.4.x to 8.0.3 ) that I explain here:

The following function just return how many records there
are inside the view v_current_connection

CREATE OR REPLACE FUNCTION sp_count ( )
RETURNS INTEGER AS'
DECLARE
c INTEGER;
BEGIN
SELECT count(*) INTO c FROM v_current_connection;
RETURN c;
END;
' LANGUAGE 'plpgsql';

I have the following select

# select count(*), sp_count() from v_current_connection;
count | sp_count
- -------+----------
977 | 978

as you can see the two count are returning different record
numbers ( in meant time other transactions are updating tables
behind the view v_current_connection ).

This isn't surprising at all, if other transactions are actively
changing the table. See the release notes for 8.0:

: Observe the following incompatibilities:
:
: In READ COMMITTED serialization mode, volatile functions now see
: the results of concurrent transactions committed up to the
: beginning of each statement within the function, rather than up to
: the beginning of the interactive command that called the function.
:
: Functions declared STABLE or IMMUTABLE always use the snapshot of
: the calling query, and therefore do not see the effects of actions
: taken after the calling query starts, whether in their own
: transaction or other transactions. Such a function must be
: read-only, too, meaning that it cannot use any SQL commands other
: than SELECT.

If you want this function to see the same snapshot as the calling query
sees, declare it STABLE.

I think I understood :-(

Just to be clear:

select work_on_connected_user(id_user) from v_connected_user;

if that function is not stable than it can work on an id_user that is not anymore
on view v_connected_user. Is this right ?

Regards
Gaetano Mendola

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.5 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFDRDPh7UpzwH2SGd4RAnPVAJ9PdcVoUoOh7U4poR0Hd9uT4l/QgACg9nXg
sebdHozcBV7t7JZslluGzB8=
=rFgE
-----END PGP SIGNATURE-----