From b1371ddcd3d869919785025d08a76c22b43a98b5 Mon Sep 17 00:00:00 2001
From: Robert Haas <rhaas@postgresql.org>
Date: Tue, 27 Aug 2024 11:30:39 -0400
Subject: [PATCH v2 2/2] Allow extensions to mark an individual IndexOptInfo as
 disabled.

As a demonstration that we definitely shouldn't commit to the real tree,
includes an example contrib module, initial_vowels_are_evil.
---
 contrib/Makefile                              |  1 +
 contrib/initial_vowels_are_evil/Makefile      | 17 +++++++
 .../initial_vowels_are_evil.c                 | 45 +++++++++++++++++++
 contrib/initial_vowels_are_evil/meson.build   | 12 +++++
 contrib/meson.build                           |  1 +
 src/backend/optimizer/util/pathnode.c         |  8 ++++
 src/include/nodes/pathnodes.h                 |  2 +
 7 files changed, 86 insertions(+)
 create mode 100644 contrib/initial_vowels_are_evil/Makefile
 create mode 100644 contrib/initial_vowels_are_evil/initial_vowels_are_evil.c
 create mode 100644 contrib/initial_vowels_are_evil/meson.build

diff --git a/contrib/Makefile b/contrib/Makefile
index abd780f277..5478b19832 100644
--- a/contrib/Makefile
+++ b/contrib/Makefile
@@ -24,6 +24,7 @@ SUBDIRS = \
 		hstore		\
 		intagg		\
 		intarray	\
+		initial_vowels_are_evil \
 		isn		\
 		lo		\
 		ltree		\
diff --git a/contrib/initial_vowels_are_evil/Makefile b/contrib/initial_vowels_are_evil/Makefile
new file mode 100644
index 0000000000..14955651cb
--- /dev/null
+++ b/contrib/initial_vowels_are_evil/Makefile
@@ -0,0 +1,17 @@
+# contrib/initial_vowels_are_evil/Makefile
+
+MODULE_big = initial_vowels_are_evil
+OBJS = \
+	$(WIN32RES) \
+	initial_vowels_are_evil.o
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = contrib/initial_vowels_are_evil
+top_builddir = ../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
diff --git a/contrib/initial_vowels_are_evil/initial_vowels_are_evil.c b/contrib/initial_vowels_are_evil/initial_vowels_are_evil.c
new file mode 100644
index 0000000000..80ccce030a
--- /dev/null
+++ b/contrib/initial_vowels_are_evil/initial_vowels_are_evil.c
@@ -0,0 +1,45 @@
+/*-------------------------------------------------------------------------
+ *
+ * initial_vowels_are_evil.c
+ *	  disable indexes whose names start with a vowel
+ *
+ * Copyright (c) 2016-2024, PostgreSQL Global Development Group
+ *
+ *	  contrib/initial_vowels_are_evil/initial_vowels_are_evil.c
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "fmgr.h"
+#include "nodes/pathnodes.h"
+#include "optimizer/plancat.h"
+#include "utils/lsyscache.h"
+
+static void ivae_get_relation_info(PlannerInfo *root, 
+								   Oid relationObjectId,
+								   bool inhparent,
+								   RelOptInfo *rel);
+
+static get_relation_info_hook_type prev_get_relation_info_hook = NULL;
+
+PG_MODULE_MAGIC;
+
+void
+_PG_init(void)
+{
+	prev_get_relation_info_hook = get_relation_info_hook;
+	get_relation_info_hook = ivae_get_relation_info;
+}
+
+static void
+ivae_get_relation_info(PlannerInfo *root, Oid relationObjectId,
+					   bool inhparent, RelOptInfo *rel)
+{
+	foreach_node(IndexOptInfo, index, rel->indexlist)
+	{
+		char *name = get_rel_name(index->indexoid);
+
+		if (name != NULL && strchr("aeiouAEIOU", name[0]) != NULL)
+			index->disabled = true;
+	}
+}
diff --git a/contrib/initial_vowels_are_evil/meson.build b/contrib/initial_vowels_are_evil/meson.build
new file mode 100644
index 0000000000..7f7fa72b53
--- /dev/null
+++ b/contrib/initial_vowels_are_evil/meson.build
@@ -0,0 +1,12 @@
+# Copyright (c) 2022-2024, PostgreSQL Global Development Group
+
+initial_vowels_are_evil_sources = files(
+  'initial_vowels_are_evil.c',
+)
+
+initial_vowels_are_evil = shared_module('initial_vowels_are_evil',
+  initial_vowels_are_evil_sources,
+  kwargs: contrib_mod_args,
+)
+
+contrib_targets += initial_vowels_are_evil
diff --git a/contrib/meson.build b/contrib/meson.build
index 14a8906865..5f87711c2d 100644
--- a/contrib/meson.build
+++ b/contrib/meson.build
@@ -32,6 +32,7 @@ subdir('fuzzystrmatch')
 subdir('hstore')
 subdir('hstore_plperl')
 subdir('hstore_plpython')
+subdir('initial_vowels_are_evil')
 subdir('intagg')
 subdir('intarray')
 subdir('isn')
diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c
index 77ed747437..e85b4e5e73 100644
--- a/src/backend/optimizer/util/pathnode.c
+++ b/src/backend/optimizer/util/pathnode.c
@@ -1079,6 +1079,14 @@ create_index_path(PlannerInfo *root,
 
 	cost_index(pathnode, root, loop_count, partial_path);
 
+	/*
+	 * cost_index will set disabled_nodes to 1 if this rel is not allowed to
+	 * use index scans in general, but it doesn't have the IndexOptInfo to know
+	 * whether this specific index has been disabled.
+	 */
+	if (index->disabled)
+		pathnode->path.disabled_nodes = 1;
+
 	return pathnode;
 }
 
diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h
index bbff482cec..ece8ce76ca 100644
--- a/src/include/nodes/pathnodes.h
+++ b/src/include/nodes/pathnodes.h
@@ -1209,6 +1209,8 @@ struct IndexOptInfo
 	bool		unique;
 	/* is uniqueness enforced immediately? */
 	bool		immediate;
+	/* true if paths using this index should be marked disabled */
+	bool		disabled;
 	/* true if index doesn't really exist */
 	bool		hypothetical;
 
-- 
2.39.3 (Apple Git-145)

