On 2013-08-30 23:05:25 +0200, Andres Freund wrote:
> On 2013-08-30 23:00:15 +0200, Andres Freund wrote:
> > Hi,
> > 
> > 
> > On 2013-08-30 20:46:27 +0000, te...@elde.net wrote:
> > > I'm getting "out of binary heap slots", which offcourse spoils the fun of
> > > the query.
> > 
> > > Explain analyze gives this plan (again anonymized a bit, but can send 
> > > proper
> > > off-list):
> > 
> > Since I reviewed the patch that introduced that message, I'd be
> > interested in getting that. Ideally in a state where I can reproduce the
> > issue in a new cluster.
> 
> No need, found the bug. And I think can build a testcase myself.
> 
> ExecReScanMergeAppend resets ms_initialized, but doesn't clear the
> binaryheap. Thus no new elements fit.

Ok, patch for that attached. Should we add
SELECT (SELECT g.i FROM ((SELECT random()::int ORDER BY 1 OFFSET 0) UNION ALL 
(SELECT random()::int ORDER BY 1 OFFSET 0)) f(i) ORDER BY f.i LIMIT 1) FROM 
generate_series(1, 10) g(i);
as a regression test? I slightly on the "no" side...

Greetings,

Andres Freund

-- 
 Andres Freund                     http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services
>From 1f6eae650b475dfe80868c78fcd805e3d49f0d71 Mon Sep 17 00:00:00 2001
From: Andres Freund <and...@anarazel.de>
Date: Fri, 30 Aug 2013 23:38:40 +0200
Subject: [PATCH] Reset the binary heap in merge append 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 the generic binaryheap
implementation.

Per bugreport from Terje Elde in bug #8410.
---
 src/backend/executor/nodeMergeAppend.c |  1 +
 src/backend/lib/binaryheap.c           | 18 ++++++++++++++++--
 src/include/lib/binaryheap.h           |  1 +
 3 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/src/backend/executor/nodeMergeAppend.c b/src/backend/executor/nodeMergeAppend.c
index 5a48f7a..c3edd61 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 4b4fc94..14fe24f 100644
--- a/src/backend/lib/binaryheap.c
+++ b/src/backend/lib/binaryheap.c
@@ -37,16 +37,30 @@ binaryheap_allocate(int capacity, binaryheap_comparator compare, void *arg)
 
 	sz = offsetof(binaryheap, bh_nodes) +sizeof(Datum) * capacity;
 	heap = palloc(sz);
-	heap->bh_size = 0;
 	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 loosing it's ephemeral state, but not the
+ * parameters passed at allocation.
+ */
+void
+binaryheap_reset(binaryheap *heap)
+{
+	heap->bh_size = 0;
+	heap->bh_has_heap_property = true;
+}
+
+/*
  * binaryheap_free
  *
  * Releases memory used by the given binaryheap.
diff --git a/src/include/lib/binaryheap.h b/src/include/lib/binaryheap.h
index 1e99e72..85cafe4 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);
-- 
1.8.2.rc2.4.g7799588.dirty

-- 
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs

Reply via email to