v1-0001-Reindex-toast-table-s-index-before-main-table-s-i.patch

application/octet-stream

Filename: v1-0001-Reindex-toast-table-s-index-before-main-table-s-i.patch
Type: application/octet-stream
Part: 0
Message: Re: BUG #18016: REINDEX TABLE failure

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: format-patch
Series: patch v1-0001
Subject: Reindex toast table's index before main table's indexes
File+
src/backend/catalog/index.c 30 24
From 4bfca93755e77c91ed9f309acdc6ffecae32ab4d Mon Sep 17 00:00:00 2001
From: Gurjeet Singh <gurjeet@singh.im>
Date: Mon, 10 Jul 2023 09:10:43 -0700
Subject: [PATCH v1] Reindex toast table's index before main table's indexes

Doing so helps in cases where a corruption in toast table's index would
otherwise prevent reindexing of main table's indexes.

While at it, perform minor wordsmithing, and benign whitespace changes
in the neighboring code.
---
 src/backend/catalog/index.c | 54 ++++++++++++++++++++-----------------
 1 file changed, 30 insertions(+), 24 deletions(-)

diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 67b743e251..b6230254a5 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -3878,7 +3878,7 @@ reindex_relation(Oid relid, int flags, ReindexParams *params)
 	Oid			toast_relid;
 	List	   *indexIds;
 	char		persistence;
-	bool		result;
+	bool		result = false;
 	ListCell   *indexId;
 	int			i;
 
@@ -3908,7 +3908,7 @@ reindex_relation(Oid relid, int flags, ReindexParams *params)
 	toast_relid = rel->rd_rel->reltoastrelid;
 
 	/*
-	 * Get the list of index OIDs for this relation.  (We trust to the
+	 * Get the list of index OIDs for this relation.  (We trust the
 	 * relcache to get this with a sequential scan if ignoring system
 	 * indexes.)
 	 */
@@ -3926,6 +3926,31 @@ reindex_relation(Oid relid, int flags, ReindexParams *params)
 		CommandCounterIncrement();
 	}
 
+	/*
+	 * Reindex the secondary toast table, if any, before the indexes on main
+	 * table. This helps in cases where a corruption in toast table's index
+	 * would otherwise prevent reindexing of main table's indexes.
+	 *
+	 * This should be done after the suppression of the use of indexes (above),
+	 * because the recursive call to reindex_relation() below will invoke
+	 * CommandCounterIncrement(), which may prevent enumeration of the indexes
+	 * on the table.
+	 */
+	if ((flags & REINDEX_REL_PROCESS_TOAST) && OidIsValid(toast_relid))
+	{
+		/*
+		 * Note that this should fail if the toast relation is missing, so
+		 * reset REINDEXOPT_MISSING_OK.  Even if a new tablespace is set for
+		 * the parent relation, the indexes on its toast table are not moved.
+		 * This rule is enforced by setting tablespaceOid to InvalidOid.
+		 */
+		ReindexParams newparams = *params;
+
+		newparams.options &= ~(REINDEXOPT_MISSING_OK);
+		newparams.tablespaceOid = InvalidOid;
+		result |= reindex_relation(toast_relid, flags, &newparams);
+	}
+
 	/*
 	 * Compute persistence of indexes: same as that of owning rel, unless
 	 * caller specified otherwise.
@@ -3941,8 +3966,8 @@ reindex_relation(Oid relid, int flags, ReindexParams *params)
 	i = 1;
 	foreach(indexId, indexIds)
 	{
-		Oid			indexOid = lfirst_oid(indexId);
-		Oid			indexNamespaceId = get_rel_namespace(indexOid);
+		Oid indexOid = lfirst_oid(indexId);
+		Oid indexNamespaceId = get_rel_namespace(indexOid);
 
 		/*
 		 * Skip any invalid indexes on a TOAST table.  These can only be
@@ -3979,26 +4004,7 @@ reindex_relation(Oid relid, int flags, ReindexParams *params)
 	 */
 	table_close(rel, NoLock);
 
-	result = (indexIds != NIL);
-
-	/*
-	 * If the relation has a secondary toast rel, reindex that too while we
-	 * still hold the lock on the main table.
-	 */
-	if ((flags & REINDEX_REL_PROCESS_TOAST) && OidIsValid(toast_relid))
-	{
-		/*
-		 * Note that this should fail if the toast relation is missing, so
-		 * reset REINDEXOPT_MISSING_OK.  Even if a new tablespace is set for
-		 * the parent relation, the indexes on its toast table are not moved.
-		 * This rule is enforced by setting tablespaceOid to InvalidOid.
-		 */
-		ReindexParams newparams = *params;
-
-		newparams.options &= ~(REINDEXOPT_MISSING_OK);
-		newparams.tablespaceOid = InvalidOid;
-		result |= reindex_relation(toast_relid, flags, &newparams);
-	}
+	result |= (indexIds != NIL);
 
 	return result;
 }
-- 
2.35.1