From 8e2b71d2d0381f7acc820a2400580a1e3a6add8c Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Fri, 30 Aug 2013 19:15:21 -0400
Subject: [PATCH] Reset the binary heap in MergeAppend rescans.

Failing to do so can cause queries to return wrong data, error out or crash.
This requires adding a new binaryheap_reset() method to binaryheap.c,
but that probably should have been there anyway.

Per bug #8410 from Terje Elde.  Diagnosis and patch by Andres Freund.
---
 src/backend/executor/nodeMergeAppend.c |  1 +
 src/backend/lib/binaryheap.c           | 20 +++++++++++++++++---
 src/include/lib/binaryheap.h           |  1 +
 3 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/src/backend/executor/nodeMergeAppend.c b/src/backend/executor/nodeMergeAppend.c
index 5a48f7ab13b..c3edd618591 100644
--- a/src/backend/executor/nodeMergeAppend.c
+++ b/src/backend/executor/nodeMergeAppend.c
@@ -297,5 +297,6 @@ ExecReScanMergeAppend(MergeAppendState *node)
 		if (subnode->chgParam == NULL)
 			ExecReScan(subnode);
 	}
+	binaryheap_reset(node->ms_heap);
 	node->ms_initialized = false;
 }
diff --git a/src/backend/lib/binaryheap.c b/src/backend/lib/binaryheap.c
index 4b4fc945c32..7125970a50f 100644
--- a/src/backend/lib/binaryheap.c
+++ b/src/backend/lib/binaryheap.c
@@ -36,16 +36,30 @@ binaryheap_allocate(int capacity, binaryheap_comparator compare, void *arg)
 	binaryheap *heap;
 
 	sz = offsetof(binaryheap, bh_nodes) +sizeof(Datum) * capacity;
-	heap = palloc(sz);
-	heap->bh_size = 0;
+	heap = (binaryheap *) palloc(sz);
 	heap->bh_space = capacity;
-	heap->bh_has_heap_property = true;
 	heap->bh_compare = compare;
 	heap->bh_arg = arg;
 
+	heap->bh_size = 0;
+	heap->bh_has_heap_property = true;
+
 	return heap;
 }
 
+/*
+ * binaryheap_reset
+ *
+ * Resets the heap to an empty state, losing its data content but not the
+ * parameters passed at allocation.
+ */
+void
+binaryheap_reset(binaryheap *heap)
+{
+	heap->bh_size = 0;
+	heap->bh_has_heap_property = true;
+}
+
 /*
  * binaryheap_free
  *
diff --git a/src/include/lib/binaryheap.h b/src/include/lib/binaryheap.h
index 1e99e72e515..85cafe4d4dd 100644
--- a/src/include/lib/binaryheap.h
+++ b/src/include/lib/binaryheap.h
@@ -40,6 +40,7 @@ typedef struct binaryheap
 extern binaryheap *binaryheap_allocate(int capacity,
 					binaryheap_comparator compare,
 					void *arg);
+extern void binaryheap_reset(binaryheap *heap);
 extern void binaryheap_free(binaryheap *heap);
 extern void binaryheap_add_unordered(binaryheap *heap, Datum d);
 extern void binaryheap_build(binaryheap *heap);
-- 
GitLab