From 4acba5b4be933225f42acc5df4d7a52b4f4afdc3 Mon Sep 17 00:00:00 2001
From: Alexander Korotkov <akorotkov@postgresql.org>
Date: Thu, 14 Mar 2024 00:53:05 +0200
Subject: [PATCH 4/8] Let table AM override reloptions for indexes built on its
 tables

---
 src/backend/access/common/reloptions.c   |  3 ++-
 src/backend/access/heap/heapam_handler.c |  8 ++++++++
 src/backend/commands/indexcmds.c         |  3 ++-
 src/backend/commands/tablecmds.c         |  9 +++++++-
 src/backend/utils/cache/relcache.c       | 24 ++++++++++++++++++++--
 src/include/access/tableam.h             | 26 ++++++++++++++++++++++++
 6 files changed, 68 insertions(+), 5 deletions(-)

diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 963995388bb..00088240cdd 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -1411,7 +1411,8 @@ extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,
 			break;
 		case RELKIND_INDEX:
 		case RELKIND_PARTITIONED_INDEX:
-			options = index_reloptions(amoptions, datum, false);
+			options = tableam_indexoptions(tableam, amoptions, classForm->relkind,
+										   datum, false);
 			break;
 		case RELKIND_FOREIGN_TABLE:
 			options = NULL;
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 590413bab9a..c560f70ba25 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -2444,6 +2444,13 @@ heapam_reloptions(char relkind, Datum reloptions, bool validate)
 	return heap_reloptions(relkind, reloptions, validate);
 }
 
+static bytea *
+heapam_indexoptions(amoptions_function amoptions, char relkind,
+					Datum reloptions, bool validate)
+{
+	return index_reloptions(amoptions, reloptions, validate);
+}
+
 
 /* ------------------------------------------------------------------------
  * Planner related callbacks for the heap AM
@@ -2949,6 +2956,7 @@ static const TableAmRoutine heapam_methods = {
 	.relation_toast_am = heapam_relation_toast_am,
 	.relation_fetch_toast_slice = heap_fetch_toast_slice,
 	.reloptions = heapam_reloptions,
+	.indexoptions = heapam_indexoptions,
 
 	.relation_estimate_size = heapam_estimate_rel_size,
 
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index d9016ef487b..e78598c10e1 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -899,7 +899,8 @@ DefineIndex(Oid tableId,
 	reloptions = transformRelOptions((Datum) 0, stmt->options,
 									 NULL, NULL, false, false);
 
-	(void) index_reloptions(amoptions, reloptions, true);
+	(void) tableam_indexoptions(rel->rd_tableam, amoptions, RELKIND_INDEX,
+								reloptions, true);
 
 	/*
 	 * Prepare arguments for index_create, primarily an IndexInfo structure.
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 6fc815666bf..eccd1131a5c 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -15539,7 +15539,14 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation,
 			break;
 		case RELKIND_INDEX:
 		case RELKIND_PARTITIONED_INDEX:
-			(void) index_reloptions(rel->rd_indam->amoptions, newOptions, true);
+			{
+				Relation	tbl = relation_open(rel->rd_index->indrelid,
+												AccessShareLock);
+
+				tableam_indexoptions(tbl->rd_tableam, rel->rd_indam->amoptions,
+									 rel->rd_rel->relkind, newOptions, true);
+				relation_close(tbl, AccessShareLock);
+			}
 			break;
 		default:
 			ereport(ERROR,
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 039c0d3eef4..4343deb4ee3 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -477,15 +477,35 @@ RelationParseRelOptions(Relation relation, HeapTuple tuple)
 	{
 		case RELKIND_RELATION:
 		case RELKIND_TOASTVALUE:
-		case RELKIND_VIEW:
 		case RELKIND_MATVIEW:
+		case RELKIND_VIEW:
 		case RELKIND_PARTITIONED_TABLE:
 			tableam = relation->rd_tableam;
 			amoptsfn = NULL;
 			break;
 		case RELKIND_INDEX:
 		case RELKIND_PARTITIONED_INDEX:
-			amoptsfn = relation->rd_indam->amoptions;
+			{
+				Form_pg_class classForm;
+				HeapTuple	classTup;
+
+				/* fetch the relation's relcache entry */
+				if (relation->rd_index->indrelid >= FirstNormalObjectId)
+				{
+					classTup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relation->rd_index->indrelid));
+					classForm = (Form_pg_class) GETSTRUCT(classTup);
+					if (classForm->relam >= FirstNormalObjectId)
+						tableam = GetTableAmRoutineByAmOid(classForm->relam);
+					else
+						tableam = GetHeapamTableAmRoutine();
+					heap_freetuple(classTup);
+				}
+				else
+				{
+					tableam = GetHeapamTableAmRoutine();
+				}
+				amoptsfn = relation->rd_indam->amoptions;
+			}
 			break;
 		default:
 			return;
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index c4cdae5903c..48f078309f7 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -17,6 +17,7 @@
 #ifndef TABLEAM_H
 #define TABLEAM_H
 
+#include "access/amapi.h"
 #include "access/relscan.h"
 #include "access/sdir.h"
 #include "access/xact.h"
@@ -757,6 +758,13 @@ typedef struct TableAmRoutine
 	 */
 	bytea	   *(*reloptions) (char relkind, Datum reloptions, bool validate);
 
+	/*
+	 * Parse table AM-specific index options.  Useful for table AM to define
+	 * new index options or override existing index options.
+	 */
+	bytea	   *(*indexoptions) (amoptions_function amoptions, char relkind,
+								 Datum reloptions, bool validate);
+
 
 	/* ------------------------------------------------------------------------
 	 * Planner related functions.
@@ -1971,6 +1979,24 @@ tableam_reloptions(const TableAmRoutine *tableam, char relkind,
 	return tableam->reloptions(relkind, reloptions, validate);
 }
 
+extern bytea *index_reloptions(amoptions_function amoptions, Datum reloptions,
+							   bool validate);
+
+/*
+ * Parse index options.  Gives table AM a chance to override index-specific
+ * options defined in 'amoptions'.
+ */
+static inline bytea *
+tableam_indexoptions(const TableAmRoutine *tableam,
+					 amoptions_function amoptions, char relkind,
+					 Datum reloptions, bool validate)
+{
+	if (tableam)
+		return tableam->indexoptions(amoptions, relkind, reloptions, validate);
+	else
+		return index_reloptions(amoptions, reloptions, validate);
+}
+
 
 /* ----------------------------------------------------------------------------
  * Planner related functionality
-- 
2.39.3 (Apple Git-145)

