From bab64ef9e8bc56fa5db9bd41cefb54c3d8051dbe Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Fri, 8 May 2015 22:22:05 +0200
Subject: [PATCH] Fix two problems in infer_arbiter_indexes().

The first is a pretty simple bug where a relcache entry is used after
the relation is closed. In this particular situation it does not appear
to have bad consequences unless compiled with RELCACHE_FORCE_RELEASE.

The second is that infer_arbiter_indexes() skipped indexes that aren't
yet valid according to indcheckxmin. That's not required here, because
uniqueness checks don't care about visibility according to an older
snapshot.  While thats not really a bug, it makes things undesirably
non-deterministic.  There is some hope that this explains a test failure
on buildfarm member jaguarundi.

Discussion: 9096.1431102730@sss.pgh.pa.us
---
 src/backend/optimizer/util/plancat.c | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 8bcc5064a37..894e0db802d 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -547,13 +547,11 @@ infer_arbiter_indexes(PlannerInfo *root)
 			goto next;
 
 		/*
-		 * If the index is valid, but cannot yet be used, ignore it. See
-		 * src/backend/access/heap/README.HOT for discussion.
+		 * Note that we do not perform a check against indcheckxmin (like
+		 * e.g. get_relation_info()) here to eliminate candidates, because
+		 * uniqueness checking only cares about the most recently committed
+		 * tuple versions.
 		 */
-		if (idxForm->indcheckxmin &&
-			!TransactionIdPrecedes(HeapTupleHeaderGetXmin(idxRel->rd_indextuple->t_data),
-								   TransactionXmin))
-			goto next;
 
 		/*
 		 * Look for match on "ON constraint_name" variant, which may not be
@@ -566,10 +564,10 @@ infer_arbiter_indexes(PlannerInfo *root)
 						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
 						 errmsg("ON CONFLICT DO UPDATE not supported with exclusion constraints")));
 
+			candidates = lappend_oid(candidates, idxForm->indexrelid);
 			list_free(indexList);
 			index_close(idxRel, NoLock);
 			heap_close(relation, NoLock);
-			candidates = lappend_oid(candidates, idxForm->indexrelid);
 			return candidates;
 		}
 		else if (indexOidFromConstraint != InvalidOid)
-- 
GitLab