BUG #19107: The hold cursor is unexpectedly released during rollback

Started by PG Bug reporting form10 months ago4 messagesbugs
Beta feature

Hackorum builds and tests every patch posted to the lists, not only commitfest submissions. This is Hackorum's own CI rather than the PostgreSQL project's, and it is still under testing - please report anything that looks wrong.

won't retrysuccessCI history

You can run a PostgreSQL built from this patch straight from Docker, with no checkout and no build:

docker run --rm -p 5432:5432 ghcr.io/hackorum-dev/postgres-patch:t73381
psql -h localhost -U postgres

Built from patchset v2 (message #2), July 27, 2026 at 06:30 AM.

Every patchset is also pushed to a branch of our PostgreSQL fork, so you can check out the same tree CI built. Without a PostgreSQL checkout:

git clone --branch t73381_2 https://github.com/hackorum-dev/postgres.git

In a checkout you already have, add the fork once:

git remote add hackorum https://github.com/hackorum-dev/postgres.git

then, for this patchset and every later one:

git fetch hackorum t73381_2 && git checkout t73381_2

Patchset v2 (message #2) is on t73381_2

Jump to latest
#1PG Bug reporting form
noreply@postgresql.org

The following bug has been logged on the website:

Bug reference: 19107
Logged by: Man Zeng
Email address: zengman@halodbtech.com
PostgreSQL version: 18.0
Operating system: Ubuntu 24.04
Description:

Hi, hackers.

While I was writing test cases for the hold cursor, I unexpectedly
discovered that commit and rollback handle it inconsistently—rollback
unexpectedly releases the hold cursor. Should this be regarded as a bug?

--
Regrads,
Man Zeng

postgres=# -- ok
postgres=# DO $$
DECLARE
val int;
BEGIN
FOR val IN SELECT generate_series(1,10) LOOP
raise notice 'val = %', val;
IF val % 2 = 0 THEN
COMMIT;
ELSE
ROLLBACK;
END IF;
END LOOP;
END; $$;
NOTICE: val = 1
NOTICE: val = 2
NOTICE: val = 3
NOTICE: val = 4
NOTICE: val = 5
NOTICE: val = 6
NOTICE: val = 7
NOTICE: val = 8
NOTICE: val = 9
NOTICE: val = 10
DO
postgres=#
postgres=# -- hold_cursor commit ok
postgres=# do $$
declare
p_CurData refcursor := 'hold_cursor';
val int;
begin
execute 'declare hold_cursor CURSOR WITH HOLD FOR SELECT 42';
loop
fetch p_CurData into val;
exit when val is null;
raise notice 'val = %', val;
commit;
end loop;
close p_CurData;
end; $$;
NOTICE: val = 42
DO
postgres=#
postgres=# -- hold_cursor rollback error
postgres=# do $$
declare
p_CurData refcursor := 'hold_cursor';
val int;
begin
execute 'DECLARE hold_cursor CURSOR WITH HOLD FOR SELECT 42';
loop
fetch p_CurData into val;
exit when val is null;
raise notice 'val = %', val;
rollback;
end loop;
close p_CurData;
end; $$;
NOTICE: val = 42
ERROR: cursor "hold_cursor" does not exist
CONTEXT: PL/pgSQL function inline_code_block line 8 at FETCH

#2zengman
zengman@halodbtech.com
In reply to: PG Bug reporting form (#1)
Re:BUG #19107: The hold cursor is unexpectedly released during rollback

If this is indeed a bug, a simple patch is attached to fix this issue.

Attachments:

t73381_2
001_rollback_no_release_holdcursor.patchapplication/octet-stream; charset=gb18030; name=001_rollback_no_release_holdcursor.patchDownload+77-0
#3Tom Lane
tgl@sss.pgh.pa.us
In reply to: PG Bug reporting form (#1)
Re: BUG #19107: The hold cursor is unexpectedly released during rollback

PG Bug reporting form <noreply@postgresql.org> writes:

While I was writing test cases for the hold cursor, I unexpectedly
discovered that commit and rollback handle it inconsistently—rollback
unexpectedly releases the hold cursor. Should this be regarded as a bug?

No, that's intentional. The rollback might be cleaning up a failure
in the held cursor.

regards, tom lane

#4zengman
zengman@halodbtech.com
In reply to: Tom Lane (#3)
Re: BUG #19107: The hold cursor is unexpectedly released during rollback

Oh, I didn't think of that—thank you so much for your guidance!

Regrads,
Man Zeng