aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/cache/relcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/cache/relcache.c')
-rw-r--r--src/backend/utils/cache/relcache.c63
1 files changed, 46 insertions, 17 deletions
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 4d0254f8e07..8fb7a750d74 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -3166,39 +3166,68 @@ RelationSetNewRelfilenode(Relation relation, char persistence,
RelationDropStorage(relation);
/*
- * Now update the pg_class row. However, if we're dealing with a mapped
- * index, pg_class.relfilenode doesn't change; instead we have to send the
- * update to the relation mapper.
+ * If we're dealing with a mapped index, pg_class.relfilenode doesn't
+ * change; instead we have to send the update to the relation mapper.
+ *
+ * For mapped indexes, we don't actually change the pg_class entry at all;
+ * this is essential when reindexing pg_class itself. That leaves us with
+ * possibly-inaccurate values of relpages etc, but those will be fixed up
+ * later.
*/
if (RelationIsMapped(relation))
+ {
+ /* This case is only supported for indexes */
+ Assert(relation->rd_rel->relkind == RELKIND_INDEX);
+
+ /* Since we're not updating pg_class, these had better not change */
+ Assert(classform->relfrozenxid == freezeXid);
+ Assert(classform->relminmxid == minmulti);
+ Assert(classform->relpersistence == persistence);
+
+ /*
+ * In some code paths it's possible that the tuple update we'd
+ * otherwise do here is the only thing that would assign an XID for
+ * the current transaction. However, we must have an XID to delete
+ * files, so make sure one is assigned.
+ */
+ (void) GetCurrentTransactionId();
+
+ /* Do the deed */
RelationMapUpdateMap(RelationGetRelid(relation),
newrelfilenode,
relation->rd_rel->relisshared,
false);
+
+ /* Since we're not updating pg_class, must trigger inval manually */
+ CacheInvalidateRelcache(relation);
+ }
else
+ {
+ /* Normal case, update the pg_class entry */
classform->relfilenode = newrelfilenode;
- /* These changes are safe even for a mapped relation */
- if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
- {
- classform->relpages = 0; /* it's empty until further notice */
- classform->reltuples = 0;
- classform->relallvisible = 0;
- }
- classform->relfrozenxid = freezeXid;
- classform->relminmxid = minmulti;
- classform->relpersistence = persistence;
+ /* relpages etc. never change for sequences */
+ if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
+ {
+ classform->relpages = 0; /* it's empty until further notice */
+ classform->reltuples = 0;
+ classform->relallvisible = 0;
+ }
+ classform->relfrozenxid = freezeXid;
+ classform->relminmxid = minmulti;
+ classform->relpersistence = persistence;
- simple_heap_update(pg_class, &tuple->t_self, tuple);
- CatalogUpdateIndexes(pg_class, tuple);
+ simple_heap_update(pg_class, &tuple->t_self, tuple);
+ CatalogUpdateIndexes(pg_class, tuple);
+ }
heap_freetuple(tuple);
heap_close(pg_class, RowExclusiveLock);
/*
- * Make the pg_class row change visible, as well as the relation map
- * change if any. This will cause the relcache entry to get updated, too.
+ * Make the pg_class row change or relation map change visible. This will
+ * cause the relcache entry to get updated, too.
*/
CommandCounterIncrement();