From 6e1a942432f7aa43555c58e882dc404d44554e51 Mon Sep 17 00:00:00 2001
From: Andrey <amborodin@acm.org>
Date: Mon, 10 Jun 2019 11:54:59 +0500
Subject: [PATCH 1/3] function relopt for gist build

---
 src/backend/access/common/reloptions.c | 12 +++++++++++
 src/backend/access/gist/gistbuild.c    | 30 ++++++++++++++++++++++++++
 src/backend/access/gist/gistutil.c     |  3 ++-
 src/include/access/gist_private.h      |  2 ++
 4 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 4d0d24be0b..cd9aa97437 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -450,6 +450,18 @@ static relopt_string stringRelOpts[] =
 		gistValidateBufferingOption,
 		"auto"
 	},
+	{
+		{
+			"fast_build_sort_function",
+			"Function for presorting data instead of usual penalty\\split inserts",
+			RELOPT_KIND_GIST,
+			AccessExclusiveLock
+		},
+		0,
+		true,
+		gistValidateBuildFuncOption,
+		NULL
+	},
 	{
 		{
 			"check_option",
diff --git a/src/backend/access/gist/gistbuild.c b/src/backend/access/gist/gistbuild.c
index ecef0ff072..e7112590b8 100644
--- a/src/backend/access/gist/gistbuild.c
+++ b/src/backend/access/gist/gistbuild.c
@@ -22,12 +22,15 @@
 #include "access/tableam.h"
 #include "access/xloginsert.h"
 #include "catalog/index.h"
+#include "catalog/pg_type.h"
 #include "miscadmin.h"
 #include "optimizer/optimizer.h"
+#include "parser/parse_func.h"
 #include "storage/bufmgr.h"
 #include "storage/smgr.h"
 #include "utils/memutils.h"
 #include "utils/rel.h"
+#include "utils/regproc.h"
 
 /* Step of index tuples for check whether to switch to buffering build mode */
 #define BUFFERING_MODE_SWITCH_CHECK_STEP 256
@@ -74,6 +77,7 @@ typedef struct
 	HTAB	   *parentMap;
 
 	GistBufferingMode bufferingMode;
+	FmgrInfo	sortFn;
 } GISTBuildState;
 
 /* prototypes for private functions */
@@ -125,6 +129,7 @@ gistbuild(Relation heap, Relation index, IndexInfo *indexInfo)
 
 	buildstate.indexrel = index;
 	buildstate.heaprel = heap;
+	buildstate.sortFn.fn_oid = InvalidOid;
 	if (index->rd_options)
 	{
 		/* Get buffering mode from the options string */
@@ -138,6 +143,16 @@ gistbuild(Relation heap, Relation index, IndexInfo *indexInfo)
 		else
 			buildstate.bufferingMode = GIST_BUFFERING_AUTO;
 
+		if (options->vl_len_ > offsetof(GiSTOptions, buildSortFunctionOffset) &&
+			options->bufferingModeOffset > 0)
+		{
+			char	*sortFuncName = (char *) options + options->buildSortFunctionOffset;
+			Oid		 argList[1] = {INTERNALOID};
+			List	*namelist = stringToQualifiedNameList(sortFuncName);
+			Oid sortFuncOid = LookupFuncName(namelist, 1, argList, false);
+			fmgr_info(sortFuncOid, &buildstate.sortFn);
+		}
+
 		fillfactor = options->fillfactor;
 	}
 	else
@@ -255,6 +270,21 @@ gistValidateBufferingOption(const char *value)
 	}
 }
 
+/*
+ * Validator for "fast_build_sort_function" reloption on GiST indexes. Allows function name
+ */
+void
+gistValidateBuildFuncOption(const char *value)
+{
+	Oid		 argList[1] = {INTERNALOID};
+	List	*namelist;
+	if (value == NULL)
+		return;
+	namelist = stringToQualifiedNameList(value);
+	/* LookupFuncName will fail if function is not existent */
+	LookupFuncName(namelist, 1, argList, false);
+}
+
 /*
  * Attempt to switch to buffering mode.
  *
diff --git a/src/backend/access/gist/gistutil.c b/src/backend/access/gist/gistutil.c
index 49df05653b..6e2ff95b5c 100644
--- a/src/backend/access/gist/gistutil.c
+++ b/src/backend/access/gist/gistutil.c
@@ -895,7 +895,8 @@ gistoptions(Datum reloptions, bool validate)
 	int			numoptions;
 	static const relopt_parse_elt tab[] = {
 		{"fillfactor", RELOPT_TYPE_INT, offsetof(GiSTOptions, fillfactor)},
-		{"buffering", RELOPT_TYPE_STRING, offsetof(GiSTOptions, bufferingModeOffset)}
+		{"buffering", RELOPT_TYPE_STRING, offsetof(GiSTOptions, bufferingModeOffset)},
+		{"fast_build_sort_function", RELOPT_TYPE_STRING, offsetof(GiSTOptions, buildSortFunctionOffset)}
 	};
 
 	options = parseRelOptions(reloptions, validate, RELOPT_KIND_GIST,
diff --git a/src/include/access/gist_private.h b/src/include/access/gist_private.h
index f80694bf9a..b4b6883f6d 100644
--- a/src/include/access/gist_private.h
+++ b/src/include/access/gist_private.h
@@ -386,6 +386,7 @@ typedef struct GiSTOptions
 	int32		vl_len_;		/* varlena header (do not touch directly!) */
 	int			fillfactor;		/* page fill factor in percent (0..100) */
 	int			bufferingModeOffset;	/* use buffering build? */
+	int			buildSortFunctionOffset;	/* used buffering sort function */
 } GiSTOptions;
 
 /* gist.c */
@@ -531,6 +532,7 @@ extern void gistSplitByKey(Relation r, Page page, IndexTuple *itup,
 extern IndexBuildResult *gistbuild(Relation heap, Relation index,
 								   struct IndexInfo *indexInfo);
 extern void gistValidateBufferingOption(const char *value);
+extern void gistValidateBuildFuncOption(const char *value);
 
 /* gistbuildbuffers.c */
 extern GISTBuildBuffers *gistInitBuildBuffers(int pagesPerBuffer, int levelStep,
-- 
2.20.1

