diff --git a/src/backend/utils/mmgr/portalmem.c b/src/backend/utils/mmgr/portalmem.c index 943da087c9f..15d5fdf448d 100644 --- a/src/backend/utils/mmgr/portalmem.c +++ b/src/backend/utils/mmgr/portalmem.c @@ -1238,6 +1238,14 @@ HoldPinnedPortals(void) HoldPortal(portal); portal->autoHeld = true; } + else if ((portal->cursorOptions & CURSOR_OPT_HOLD) && + portal->createSubid != InvalidSubTransactionId && + portal->status == PORTAL_READY) + { + /* Is it a holdable portal created in the current xact? */ + HoldPortal(portal); + portal->autoHeld = true; + } } } diff --git a/src/pl/plpgsql/src/expected/plpgsql_simple.out b/src/pl/plpgsql/src/expected/plpgsql_simple.out index da351873e74..3a6342c3abd 100644 --- a/src/pl/plpgsql/src/expected/plpgsql_simple.out +++ b/src/pl/plpgsql/src/expected/plpgsql_simple.out @@ -129,3 +129,39 @@ begin raise notice 'val = %', val; end; $$; NOTICE: val = 42 +-- Verify whether the behavior of the hold cursor is consistent during commit and rollback +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 $$ +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 +select * from pg_cursors; + name | statement | is_holdable | is_binary | is_scrollable | creation_time +------+-----------+-------------+-----------+---------------+--------------- +(0 rows) + diff --git a/src/pl/plpgsql/src/sql/plpgsql_simple.sql b/src/pl/plpgsql/src/sql/plpgsql_simple.sql index 72d8afe4500..898721ea97b 100644 --- a/src/pl/plpgsql/src/sql/plpgsql_simple.sql +++ b/src/pl/plpgsql/src/sql/plpgsql_simple.sql @@ -114,3 +114,36 @@ begin fetch p_CurData into val; raise notice 'val = %', val; end; $$; + +-- Verify whether the behavior of the hold cursor is consistent during commit and rollback +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; $$; + +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; $$; + +select * from pg_cursors;