Re: with hold cursor, cause function execute twice and wrong result

Поиск
Список
Период
Сортировка
От Merlin Moncure
Тема Re: with hold cursor, cause function execute twice and wrong result
Дата
Msg-id CAHyXU0wSDBJAM+xx3ux27=4c0GJ0W-t_RoN-GUSx5MiENCOCdQ@mail.gmail.com
обсуждение исходный текст
Ответ на with hold cursor, cause function execute twice and wrong result  (wcting163 <wcting163@163.com>)
Список pgsql-bugs
2011/12/27 wcting163 <wcting163@163.com>:
> postgres=3D# select version();
> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=
=A0=A0=A0=A0=A0=A0=A0=A0 version
> -------------------------------------------------------------------------=
-----------------------------------------------
> ---
> =A0PostgreSQL 9.0alpha5 on x86_64-unknown-linux-gnu, compiled by GCC gcc =
(GCC)
> 4.1.2 20080704 (Asianux 3.0 4.1.2-44), 64-b
> it
>
> create table test_execute(id int,name varchar(40));
> insert into test_execute values(1,'jack');
> create or replace function p_test_execute() returns void
> as
> $$
> begin
> =A0=A0=A0=A0=A0=A0=A0 raise notice 'hello world';
> =A0=A0=A0=A0=A0=A0=A0 update test_execute set id=3Did*2;
> end;
> $$ LANGUAGE plpgsql;
>
> begin;
> declare JDBC_CURS_1 cursor with hold for select p_test_execute() from
> test_execute;
> fetch 50 from JDBC_CURS_1;
> NOTICE:=A0 hello world
> end;
> NOTICE:=A0 hello world
> COMMIT
> select * from test_execute;
> =A0id | name
> ----+------
> =A0 4 | jack
>
> I expect id =3D 2, but it is **4** instead,
>
> The reason is that the function p_test_execute is executed twice, when
> *fetch*, it is first executed, and when transaction commit, because the
> cursor is a *holdable* cursor, it is executed again.
>
> I read the code, for holdable cursor, when commit, following call will
> execute:
> =A0CommitHoldablePortals-->PersistHoldablePortal-->ExecutorRewind.
>
> Is *ExecutorRewind* necessary, is it the root of this bug?
> Does *ExecutorRewind* cause plan re-execute?

while the current behavior isn't great, is this in fact a bug?  there
is no guarantee that functions in the select list are executed once
per returned row anywhere else in the system.

note, the current best way to isolate yourself from this behavior,
stuffing the function call in a CTE, works they way you are intending:

declare JDBC_CURS_1 cursor with hold for with foo as (select
p_test_execute() from test_execute) select * from foo;

merlin

В списке pgsql-bugs по дате отправления:

Предыдущее
От: Merlin Moncure
Дата:
Сообщение: Re: BUG #6365: Memory leak in insert and update
Следующее
От: Tom Lane
Дата:
Сообщение: Re: BUG #6365: Memory leak in insert and update