From a58130f1102545d4fdccca796e4fe9fc4596e650 Mon Sep 17 00:00:00 2001
From: Yuhang Qiu <iamqyh@gmail.com>
Date: Wed, 26 Aug 2026 11:57:21 +0000
Subject: [PATCH 1/3] read_stream: Allow changing the buffer access strategy

Heap scans can replace their buffer access strategy during a rescan.
A read stream retained across such a rescan would keep references to
the old strategy, which may then be freed.

Add read_stream_set_strategy() to update an idle stream. It changes the
strategy used by subsequent reads and recomputes the limit on pinned
buffers.
---
 src/backend/storage/aio/read_stream.c | 24 ++++++++++++++++++++++++
 src/include/storage/read_stream.h     |  2 ++
 2 files changed, 26 insertions(+)

diff --git a/src/backend/storage/aio/read_stream.c b/src/backend/storage/aio/read_stream.c
index e7dbbe03326..45ca5ec915d 100644
--- a/src/backend/storage/aio/read_stream.c
+++ b/src/backend/storage/aio/read_stream.c
@@ -1428,6 +1428,30 @@ read_stream_clear_strategy(ReadStream *stream)
 		stream->ios[i].op.strategy = NULL;
 }
 
+/*
+ * Change the buffer access strategy used by an idle stream.
+ *
+ * The stream must first be reset so that no reads still refer to the old
+ * strategy.  The allocation made when the stream was created cannot grow,
+ * but a new strategy may require a lower limit on pinned buffers.
+ */
+void
+read_stream_set_strategy(ReadStream *stream, BufferAccessStrategy strategy)
+{
+	Assert(stream->pinned_buffers == 0);
+	Assert(stream->ios_in_progress == 0);
+	Assert(stream->pending_read_nblocks == 0);
+
+	stream->max_pinned_buffers = Min(stream->queue_size - 1,
+									GetAccessStrategyPinLimit(strategy));
+
+	if (stream->stats)
+		stream->stats->distance_capacity = stream->max_pinned_buffers;
+
+	for (int i = 0; i < stream->max_ios; ++i)
+		stream->ios[i].op.strategy = strategy;
+}
+
 /*
  * Reset a read stream by releasing any queued up buffers, allowing the stream
  * to be used again for different blocks.  This can be used to clear an
diff --git a/src/include/storage/read_stream.h b/src/include/storage/read_stream.h
index e2dcf1be50a..38a455bba12 100644
--- a/src/include/storage/read_stream.h
+++ b/src/include/storage/read_stream.h
@@ -103,6 +103,8 @@ extern ReadStream *read_stream_begin_smgr_relation(int flags,
 extern BlockNumber read_stream_pause(ReadStream *stream);
 extern void read_stream_resume(ReadStream *stream);
 extern void read_stream_clear_strategy(ReadStream *stream);
+extern void read_stream_set_strategy(ReadStream *stream,
+									 BufferAccessStrategy strategy);
 extern void read_stream_reset(ReadStream *stream);
 extern void read_stream_end(ReadStream *stream);
 extern void read_stream_enable_stats(ReadStream *stream, struct IOStats *stats);
-- 
2.43.7

