At Mon, 28 Mar 2022 18:36:46 +0900 (JST), Kyotaro Horiguchi
<[email protected]> 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) ||