]> granicus.if.org Git - postgresql/commitdiff
Fix relcache reference leak in refresh_by_match_merge().
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 18 Mar 2014 15:36:45 +0000 (11:36 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
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);