From d3593ff34c83c20c75165624faf6d84803390b36 Mon Sep 17 00:00:00 2001
From: Jeff Davis <jeff@j-davis.com>
Date: Fri, 31 Jan 2020 16:43:41 -0800
Subject: [PATCH 1/3] Logical Tape Set: lazily allocate read buffer.

The write buffer was already lazily-allocated, so this is more
symmetric. It also means that a freshly-rewound tape (whether for
reading or writing) is not consuming memory for the buffer.
---
 src/backend/utils/sort/logtape.c | 27 ++++++++++++++++++++-------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/src/backend/utils/sort/logtape.c b/src/backend/utils/sort/logtape.c
index 42cfb1f9f98..ba6d6e1f80a 100644
--- a/src/backend/utils/sort/logtape.c
+++ b/src/backend/utils/sort/logtape.c
@@ -773,15 +773,12 @@ LogicalTapeRewindForRead(LogicalTapeSet *lts, int tapenum, size_t buffer_size)
 	lt->buffer_size = 0;
 	if (lt->firstBlockNumber != -1L)
 	{
-		lt->buffer = palloc(buffer_size);
+		/*
+		 * The buffer is lazily allocated in LogicalTapeRead(), but we set the
+		 * size here.
+		 */
 		lt->buffer_size = buffer_size;
 	}
-
-	/* Read the first block, or reset if tape is empty */
-	lt->nextBlockNumber = lt->firstBlockNumber;
-	lt->pos = 0;
-	lt->nbytes = 0;
-	ltsReadFillBuffer(lts, lt);
 }
 
 /*
@@ -830,6 +827,22 @@ LogicalTapeRead(LogicalTapeSet *lts, int tapenum,
 	lt = &lts->tapes[tapenum];
 	Assert(!lt->writing);
 
+	if (lt->buffer == NULL)
+	{
+		/* lazily allocate buffer */
+		if (lt->firstBlockNumber != -1L)
+		{
+			Assert(lt->buffer_size > 0);
+			lt->buffer = palloc(lt->buffer_size);
+		}
+
+		/* Read the first block, or reset if tape is empty */
+		lt->nextBlockNumber = lt->firstBlockNumber;
+		lt->pos = 0;
+		lt->nbytes = 0;
+		ltsReadFillBuffer(lts, lt);
+	}
+
 	while (size > 0)
 	{
 		if (lt->pos >= lt->nbytes)
-- 
2.17.1

