At Mon, 28 Mar 2022 18:36:46 +0900 (JST), Kyotaro Horiguchi <horikyota....@gmail.com> wrote in > Inserting EnsurePortalSnapshotExists() to RunFromStore fixes this but > I'm not sure where is the right place to do this..
Then, I found that portal->holdSnapshot is that. I came up with the attached. It does the follows: 1. Teach PlannedStmtRequiresSnapshot() to return true for FetchStmt. 2. Use holdSnapshot in RunFromStore if any. The rerpducer is reduced to as small as the following. CREATE TABLE t (a text); INSERT INTO t VALUES('some random text'); BEGIN; DECLARE c CURSOR FOR SELECT * FROM t; FETCH ALL IN c; But I haven't come up with a reasonable way to generate the 'some random text' yet. regards. -- Kyotaro Horiguchi NTT Open Source Software Center
diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c index 5aa5a350f3..8354029f2a 100644 --- a/src/backend/tcop/pquery.c +++ b/src/backend/tcop/pquery.c @@ -1068,6 +1068,18 @@ RunFromStore(Portal portal, ScanDirection direction, uint64 count, dest->rStartup(dest, CMD_SELECT, portal->tupDesc); + /* + * If holdSnapshot is set, that means we should use the snapshot to read + * this store. + */ + if (portal->holdSnapshot) + { + Assert(portal->portalSnapshot == 0); + PushActiveSnapshotWithLevel(portal->holdSnapshot, + portal->createLevel); + portal->portalSnapshot = GetActiveSnapshot(); + } + if (ScanDirectionIsNoMovement(direction)) { /* do nothing except start/stop the destination */ @@ -1114,6 +1126,13 @@ RunFromStore(Portal portal, ScanDirection direction, uint64 count, dest->rShutdown(dest); + if (portal->holdSnapshot) + { + Assert(portal->portalSnapshot == GetActiveSnapshot()); + PopActiveSnapshot(); + portal->portalSnapshot = NULL; + } + ExecDropSingleTupleTableSlot(slot); return current_tuple_count; @@ -1756,7 +1775,6 @@ PlannedStmtRequiresSnapshot(PlannedStmt *pstmt) IsA(utilityStmt, VariableShowStmt) || IsA(utilityStmt, ConstraintsSetStmt) || /* efficiency hacks from here down */ - IsA(utilityStmt, FetchStmt) || IsA(utilityStmt, ListenStmt) || IsA(utilityStmt, NotifyStmt) || IsA(utilityStmt, UnlistenStmt) ||