Fix relcache reference leak in refresh_by_match_merge().

One path through the loop over indexes forgot to do index_close().  Rather
than adding a fourth call, restructure slightly so that there's only one.

In passing, get rid of an unnecessary syscache lookup: the pg_index struct
for the index is already available from its relcache entry.

Per report from YAMAMOTO Takashi, though this is a bit different from his
suggested patch.  This is new code in HEAD, so no need for back-patch.
This commit is contained in:
Tom Lane 2014-03-18 11:36:45 -04:00
parent 3bd261ca18
commit f7271c4427
1 changed files with 12 additions and 27 deletions

View File

@ -609,40 +609,23 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid)
{
Oid indexoid = lfirst_oid(indexoidscan);
Relation indexRel;
HeapTuple indexTuple;
Form_pg_index indexStruct;
indexRel = index_open(indexoid, RowExclusiveLock);
indexTuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexoid));
if (!HeapTupleIsValid(indexTuple)) /* should not happen */
elog(ERROR, "cache lookup failed for index %u", indexoid);
indexStruct = (Form_pg_index) GETSTRUCT(indexTuple);
indexStruct = indexRel->rd_index;
/* We're only interested if it is unique and valid. */
if (indexStruct->indisunique && IndexIsValid(indexStruct))
/*
* We're only interested if it is unique, valid, contains no
* expressions, and is not partial.
*/
if (indexStruct->indisunique &&
IndexIsValid(indexStruct) &&
RelationGetIndexExpressions(indexRel) == NIL &&
RelationGetIndexPredicate(indexRel) == NIL)
{
int numatts = indexStruct->indnatts;
int i;
/* Skip any index on an expression. */
if (RelationGetIndexExpressions(indexRel) != NIL)
{
index_close(indexRel, NoLock);
ReleaseSysCache(indexTuple);
continue;
}
/* Skip partial indexes. */
if (RelationGetIndexPredicate(indexRel) != NIL)
{
index_close(indexRel, NoLock);
ReleaseSysCache(indexTuple);
continue;
}
/* Hold the locks, since we're about to run DML which needs them. */
index_close(indexRel, NoLock);
/* Add quals for all columns from this index. */
for (i = 0; i < numatts; i++)
{
@ -675,7 +658,9 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid)
foundUniqueIndex = true;
}
}
ReleaseSysCache(indexTuple);
/* Keep the locks, since we're about to run DML which needs them. */
index_close(indexRel, NoLock);
}
list_free(indexoidlist);