Fix relcache reference leak in refresh_by_match_merge().
authorTom Lane
Tue, 18 Mar 2014 15:36:45 +0000 (11:36 -0400)
committerTom Lane
Tue, 18 Mar 2014 15:36:53 +0000 (11:36 -0400)
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.

src/backend/commands/matview.c

index d64f1657066120ab6a9cc8bf98336440503a1819..a301d65b60e0aad27224ad795ce2655e8d42d434 100644 (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);
-
-       /* We're only interested if it is unique and valid. */
-       if (indexStruct->indisunique && IndexIsValid(indexStruct))
+       indexStruct = indexRel->rd_index;
+
+       /*
+        * 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);