From: | "Brian Ceccarelli" <bceccarelli(at)net32(dot)com> |
---|---|
To: | pgsql-bugs(at)postgresql(dot)org |
Subject: | BUG #5611: SQL Function STABLE promoting to VOLATILE |
Date: | 2010-08-10 20:30:50 |
Message-ID: | 201008102030.o7AKUo5E022936@wwwmaster.postgresql.org |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-bugs |
The following bug has been logged online:
Bug reference: 5611
Logged by: Brian Ceccarelli
Email address: bceccarelli(at)net32(dot)com
PostgreSQL version: 8.4.4
Operating system: Windows XP 32 bit and Red Hat 5.4 64 bit
Description: SQL Function STABLE promoting to VOLATILE
Details:
----------------------------------------------------------------------------
-----
--
-- Demonstration of a PL/PGSQL stable-scoped function not working.
--
-- To see the problem, run this entire script from PGAdmin. Bring
up Task Manager too.
-- After you the run this entire script, you can repeat the specific
problem by running:
--
-- select * from f_pass_4();
--
-- Note that "I am in f_return_ver_id_4() repeats once for every row
returned from f_get_table_4().
-- Postgres should only call f_return_ver_id_4() once.
-- The Problems:
--
-- 1. It seems that STABLE functions called within a SQL language
get promoted to VOLATILE.
-- Even though I declare a function STABLE, Postgres calls it
multiple times within a tranasaction.
--
-- 2. The raise notice in f_return_ver_id_4() also causes a memory
leak in PGAdmin (on Windows).
--
-- Related Problems:
--
-- Even the now() function gets called repeatedly within a stable
SQL function.
--
-- Postgres Version:
--
-- I am running Postgres 8.4.4-1 on Windows. (Windows XP 32 bit)
-- Same problem occurs on Postgres 8.4.4 on Linux-64. Red Hat 5.4.
--
-- Problem NOT in Postgres 8.2.
--
-- This problem does not happen in Postgres 8.2.
--
----------------------------------------------------------------------------
-----
drop type if exists type_pass_test cascade;
create type type_pass_test as (ver_id int8);
CREATE OR REPLACE FUNCTION f_get_table_4()
RETURNS setof type_pass_test AS
$BODY$
----------------------------------------------------------------------------
-----
--
--
----------------------------------------------------------------------------
-----
declare
r type_pass_test;
i int8;
begin
for i in 1..5
loop
r.ver_id := i;
return next r;
end loop;
return;
end;
$BODY$
language 'plpgsql' volatile;
CREATE OR REPLACE FUNCTION f_return_ver_id_4()
RETURNS int8 AS
$BODY$
----------------------------------------------------------------------------
-----
--
--
----------------------------------------------------------------------------
-----
declare
begin
raise notice 'I am in f_return_ver_id_4()';
return 1;
end;
$BODY$
language 'plpgsql' stable;
CREATE OR REPLACE FUNCTION f_do_4(ver_id_in int8)
RETURNS setof type_pass_test AS
$BODY$
----------------------------------------------------------------------------
-----
--
-- When you run f_pass_4(), f_pass_4() calls f_do_4() passing ver_id_in as
f_return_ver_id_4().
--
-- The error:
--
-- Even though f_return_ver_id_4() is a STABLE function, the select
-- statement below calls f_return_ver_id_4() once for every row coming
back from
-- f_get_table_4().
--
-- The repeat appears when I write the function in the SQL language.
-- The repeat disappears when I write the function in the PL/PGSQL
language.
-- If I add now() to the where clause, you will even see that Postgres
calls now() multiple times.
--
----------------------------------------------------------------------------
-----
select *
from f_get_table_4()
where ver_id = $1;
$BODY$
language 'SQL' stable;
/*
CREATE OR REPLACE FUNCTION f_do_4(ver_id_in int8)
RETURNS setof type_pass_test AS
$BODY$
----------------------------------------------------------------------------
-----
--
-- If I make the f_do_4(ver_id_in int8) a PL/PGSQL function, the problem
goes away.
--
----------------------------------------------------------------------------
-----
begin
return query
select *
from f_get_table_4()
where ver_id = $1;
return;
end;
$BODY$
language 'plpgsql' stable;
*/
CREATE OR REPLACE FUNCTION f_pass_4()
RETURNS int4 AS
$BODY$
----------------------------------------------------------------------------
-----
--
-- Example:
--
-- select * from f_pass_4();
--
----------------------------------------------------------------------------
-----
declare
rows_affected_w int4;
begin
select into rows_affected_w
count(*)
from f_do_4(f_return_ver_id_4());
return rows_affected_w;
end;
$BODY$
language 'plpgsql' stable;
----------------------------------------
select * from f_pass_4();
From | Date | Subject | |
---|---|---|---|
Next Message | Mark Kirkwood | 2010-08-11 02:42:40 | Re: Measuring execution time |
Previous Message | Alex Hunsaker | 2010-08-10 18:30:07 | Re: BUG #5601: cannot create language plperl; |