From 08d688a4346a5bb44f702ebbd46f75d5fc7bc01d Mon Sep 17 00:00:00 2001
From: Jeff Davis <jeff@j-davis.com>
Date: Mon, 7 Aug 2023 11:12:07 -0700
Subject: [PATCH v4 4/4] wip

---
 src/backend/utils/fmgr/fmgr.c |  9 +++--
 src/backend/utils/misc/guc.c  | 63 +++++++++++++++++++++++++++++++++++
 src/include/utils/guc.h       |  1 +
 3 files changed, 70 insertions(+), 3 deletions(-)

diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c
index 6b2d7d7be3..40c6137b01 100644
--- a/src/backend/utils/fmgr/fmgr.c
+++ b/src/backend/utils/fmgr/fmgr.c
@@ -703,9 +703,12 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
 		char		*name	 = lfirst(lc1);
 		char		*value	 = lfirst(lc2);
 
-		(void) set_config_option(name, value,
-								 context, source,
-								 action, true, 0, false);
+		if (!strcmp(name, "search_path"))
+			fast_set_search_path(value);
+		else
+			(void) set_config_option(name, value,
+									 context, source,
+									 action, true, 0, false);
 	}
 
 	/* function manager hook */
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index fa96b79192..a34a81217f 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -46,6 +46,7 @@
 #include "utils/builtins.h"
 #include "utils/conffiles.h"
 #include "utils/float.h"
+#include "utils/guc_hooks.h"
 #include "utils/guc_tables.h"
 #include "utils/memutils.h"
 #include "utils/timestamp.h"
@@ -225,6 +226,7 @@ static bool reporting_enabled;	/* true to enable GUC_REPORT */
 
 static int	GUCNestLevel = 0;	/* 1 when in main transaction */
 
+struct config_string *search_path_conf = NULL;
 
 static int	guc_var_compare(const void *a, const void *b);
 static uint32 guc_name_hash(const void *key, Size keysize);
@@ -4135,6 +4137,67 @@ set_config_option_ext(const char *name, const char *value,
 	return changeVal ? 1 : -1;
 }
 
+/*
+ * optimized version of:
+ *   set_config_option("search_path", searchPath,
+ *                     superuser() ? PGC_SUSET : PGC_USERSET,
+                       PGC_S_SESSION, GUC_ACTION_SAVE, true, 0, false);
+ *                     
+ */
+void
+fast_set_search_path(const char *searchPath)
+{
+	char		*newval	  = guc_strdup(ERROR, searchPath);
+	void		*newextra = NULL;
+	Oid			 srole	  = GetUserId();
+	GucContext	 context  = superuser() ? PGC_SUSET : PGC_USERSET;
+	GucSource    source	  = PGC_S_SESSION;
+
+	if (search_path_conf == NULL)
+	{
+		struct config_generic *record;
+		record = find_option("search_path", true, false, ERROR);
+		Assert(record != NULL);
+		search_path_conf = (struct config_string *) record;
+	}
+
+	/* Reset variables that might be set by hook */
+	GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE;
+	GUC_check_errmsg_string = NULL;
+	GUC_check_errdetail_string = NULL;
+	GUC_check_errhint_string = NULL;
+
+	if (!check_search_path(&newval, NULL, source))
+	{
+		guc_free(newval);
+		ereport(ERROR,
+				(errcode(GUC_check_errcode_value),
+				 GUC_check_errmsg_string ?
+				 errmsg_internal("%s", GUC_check_errmsg_string) :
+				 errmsg("invalid value for parameter \"%s\": \"%s\"",
+						search_path_conf->gen.name, newval ? newval : ""),
+				 GUC_check_errdetail_string ?
+				 errdetail_internal("%s", GUC_check_errdetail_string) : 0,
+				 GUC_check_errhint_string ?
+				 errhint("%s", GUC_check_errhint_string) : 0));
+	}
+
+	assign_search_path(newval, newextra);
+	set_string_field(search_path_conf, search_path_conf->variable, newval);
+	set_extra_field(&search_path_conf->gen, &search_path_conf->gen.extra,
+					newextra);
+	set_guc_source(&search_path_conf->gen, source);
+	search_path_conf->gen.scontext = context;
+	search_path_conf->gen.srole = srole;
+
+	/* Perhaps we didn't install newval anywhere */
+	if (newval && !string_field_used(search_path_conf, newval))
+		guc_free(newval);
+	/* Perhaps we didn't install newextra anywhere */
+	if (newextra && !extra_field_used(&search_path_conf->gen, newextra))
+		guc_free(newextra);
+}
+
 
 /*
  * Set the fields for source file and line number the setting came from.
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index e89083ee0e..d916ecf2ed 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -387,6 +387,7 @@ extern int	set_config_option_ext(const char *name, const char *value,
 								  Oid srole,
 								  GucAction action, bool changeVal, int elevel,
 								  bool is_reload);
+extern void fast_set_search_path(const char *searchPath);
 extern void AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt);
 extern char *GetConfigOptionByName(const char *name, const char **varname,
 								   bool missing_ok);
-- 
2.34.1

