Simplify call to rebuild relcache entry for indexes
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Thu, 31 Oct 2024 08:02:58 +0000 (10:02 +0200)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Thu, 31 Oct 2024 08:02:58 +0000 (10:02 +0200)
RelationClearRelation(rebuild == true) calls RelationReloadIndexInfo()
for indexes. We can rely on that in RelationIdGetRelation(), instead
of calling RelationReloadIndexInfo() directly. That simplifies the
code a little.

In the passing, add a comment in RelationBuildLocalRelation()
explaining why it doesn't call RelationInitIndexAccessInfo(). It's
because at index creation, it's called before the pg_index row has
been created. That's also the reason that RelationClearRelation()
still needs a special case to go through the full-blown rebuild if the
index support information in the relcache entry hasn't been populated
yet.

Reviewed-by: jian he <jian.universality@gmail.com>
Discussion: https://www.postgresql.org/message-id/9c9e8908-7b3e-4ce7-85a8-00c0e165a3d6%40iki.fi

src/backend/utils/cache/relcache.c

index c326f687eb4f5ee65a8e19059dc86ce8c816a54c..8143f0804334260843044bd784ea75e73fa64e2a 100644 (file)
@@ -2083,16 +2083,7 @@ RelationIdGetRelation(Oid relationId)
                /* revalidate cache entry if necessary */
                if (!rd->rd_isvalid)
                {
-                       /*
-                        * Indexes only have a limited number of possible schema changes,
-                        * and we don't want to use the full-blown procedure because it's
-                        * a headache for indexes that reload itself depends on.
-                        */
-                       if (rd->rd_rel->relkind == RELKIND_INDEX ||
-                               rd->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
-                               RelationReloadIndexInfo(rd);
-                       else
-                               RelationClearRelation(rd, true);
+                       RelationClearRelation(rd, true);
 
                        /*
                         * Normally entries need to be valid here, but before the relcache
@@ -2264,14 +2255,6 @@ RelationReloadIndexInfo(Relation relation)
                   !relation->rd_isvalid &&
                   relation->rd_droppedSubid == InvalidSubTransactionId);
 
-       /* Ensure it's closed at smgr level */
-       RelationCloseSmgr(relation);
-
-       /* Must free any AM cached data upon relcache flush */
-       if (relation->rd_amcache)
-               pfree(relation->rd_amcache);
-       relation->rd_amcache = NULL;
-
        /*
         * If it's a shared index, we might be called before backend startup has
         * finished selecting a database, in which case we have no way to read
@@ -2600,15 +2583,19 @@ RelationClearRelation(Relation relation, bool rebuild)
                return;
 
        /*
-        * Even non-system indexes should not be blown away if they are open and
-        * have valid index support information.  This avoids problems with active
-        * use of the index support information.  As with nailed indexes, we
-        * re-read the pg_class row to handle possible physical relocation of the
-        * index, and we check for pg_index updates too.
+        * Indexes only have a limited number of possible schema changes, and we
+        * don't want to use the full-blown procedure because it's a headache for
+        * indexes that reload itself depends on.
+        *
+        * As an exception, use the full procedure if the index access info hasn't
+        * been initialized yet.  Index creation relies on that: it first builds
+        * the relcache entry with RelationBuildLocalRelation(), creates the
+        * pg_index tuple only after that, and then relies on
+        * CommandCounterIncrement to load the pg_index contents.
         */
        if ((relation->rd_rel->relkind == RELKIND_INDEX ||
                 relation->rd_rel->relkind == RELKIND_PARTITIONED_INDEX) &&
-               relation->rd_refcnt > 0 &&
+               rebuild &&
                relation->rd_indexcxt != NULL)
        {
                if (IsTransactionState())
@@ -3720,6 +3707,12 @@ RelationBuildLocalRelation(const char *relname,
        if (RELKIND_HAS_TABLE_AM(relkind) || relkind == RELKIND_SEQUENCE)
                RelationInitTableAccessMethod(rel);
 
+       /*
+        * Leave index access method uninitialized, because the pg_index row has
+        * not been inserted at this stage of index creation yet.  The cache
+        * invalidation after pg_index row has been inserted will initialize it.
+        */
+
        /*
         * Okay to insert into the relcache hash table.
         *