Fix two problems in infer_arbiter_indexes().
authorAndres Freund <andres@anarazel.de>
Fri, 8 May 2015 20:22:05 +0000 (22:22 +0200)
committerAndres Freund <andres@anarazel.de>
Fri, 8 May 2015 20:28:23 +0000 (22:28 +0200)
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

index 8bcc5064a37984265df704e540ebb2998a336fea..894e0db802de81e0eaa506c92aeeb6a6121d4e51 100644 (file)
@@ -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)