From 2d6599f47152fe898569ba07b0a0a79e244bbb99 Mon Sep 17 00:00:00 2001
From: Teodor Sigaev <teodor@sigaev.ru>
Date: Fri, 11 Jul 2008 11:56:48 +0000
Subject: [PATCH] Add caching of query to GIN/GiST consistent function. Per
 performance gripe from nomao.com

---
 contrib/pg_trgm/trgm_gin.c  | 32 ++++++++++++++++++++++++++++----
 contrib/pg_trgm/trgm_gist.c | 22 ++++++++++++++++++++--
 2 files changed, 48 insertions(+), 6 deletions(-)

diff --git a/contrib/pg_trgm/trgm_gin.c b/contrib/pg_trgm/trgm_gin.c
index 82ac2b41c1c..7f8bda7207b 100644
--- a/contrib/pg_trgm/trgm_gin.c
+++ b/contrib/pg_trgm/trgm_gin.c
@@ -1,5 +1,5 @@
 /*
- * $PostgreSQL: pgsql/contrib/pg_trgm/trgm_gin.c,v 1.4 2008/05/17 01:28:21 adunstan Exp $ 
+ * $PostgreSQL: pgsql/contrib/pg_trgm/trgm_gin.c,v 1.5 2008/07/11 11:56:48 teodor Exp $ 
  */
 #include "trgm.h"
 
@@ -52,6 +52,16 @@ gin_extract_trgm(PG_FUNCTION_ARGS)
 	PG_RETURN_POINTER(entries);
 }
 
+/*
+ * Per call strage for consistent functions to
+ * cache computed value from query
+ */
+typedef struct PerCallConsistentStorage {
+	int		trglen;
+	text	data[1]; /* query */
+} PerCallConsistentStorage;
+#define PCCSHDR_SZ  offsetof(PerCallConsistentStorage, data)
+
 Datum
 gin_trgm_consistent(PG_FUNCTION_ARGS)
 {
@@ -60,16 +70,30 @@ gin_trgm_consistent(PG_FUNCTION_ARGS)
 	text	   *query = PG_GETARG_TEXT_P(2);
 	bool	   *recheck = (bool *) PG_GETARG_POINTER(3);
 	bool		res = FALSE;
-	TRGM	   *trg;
 	int4		i,
 				trglen,
 				ntrue = 0;
+	PerCallConsistentStorage  *pccs = (PerCallConsistentStorage*) fcinfo->flinfo->fn_extra;
 
 	/* All cases served by this function are inexact */
 	*recheck = true;
 
-	trg = generate_trgm(VARDATA(query), VARSIZE(query) - VARHDRSZ);
-	trglen = ARRNELEM(trg);
+	if ( pccs == NULL || VARSIZE(pccs->data) != VARSIZE(query) || memcmp( pccs->data, query, VARSIZE(query) ) !=0  )
+	{
+		TRGM	   *trg = generate_trgm(VARDATA(query), VARSIZE(query) - VARHDRSZ);
+
+		if ( pccs )
+			pfree(pccs);
+
+		fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt, 
+									VARSIZE(query) + PCCSHDR_SZ);
+		pccs = (PerCallConsistentStorage*) fcinfo->flinfo->fn_extra;
+
+		pccs->trglen = ARRNELEM(trg);
+		memcpy( pccs->data, query, VARSIZE(query) );
+	}
+
+	trglen = pccs->trglen;
 
 	for (i = 0; i < trglen; i++)
 		if (check[i])
diff --git a/contrib/pg_trgm/trgm_gist.c b/contrib/pg_trgm/trgm_gist.c
index 7baf4fd6978..2720d7fb707 100644
--- a/contrib/pg_trgm/trgm_gist.c
+++ b/contrib/pg_trgm/trgm_gist.c
@@ -1,5 +1,5 @@
 /*
- * $PostgreSQL: pgsql/contrib/pg_trgm/trgm_gist.c,v 1.14 2008/05/17 01:28:21 adunstan Exp $ 
+ * $PostgreSQL: pgsql/contrib/pg_trgm/trgm_gist.c,v 1.15 2008/07/11 11:56:48 teodor Exp $ 
  */
 #include "trgm.h"
 
@@ -168,12 +168,30 @@ gtrgm_consistent(PG_FUNCTION_ARGS)
 	/* Oid		subtype = PG_GETARG_OID(3); */
 	bool	   *recheck = (bool *) PG_GETARG_POINTER(4);
 	TRGM	   *key = (TRGM *) DatumGetPointer(entry->key);
-	TRGM	   *qtrg = generate_trgm(VARDATA(query), VARSIZE(query) - VARHDRSZ);
+	TRGM	   *qtrg;
 	bool		res = false;
+	char		*cache  = (char*) fcinfo->flinfo->fn_extra;
 
 	/* All cases served by this function are exact */
 	*recheck = false;
 
+	if ( cache == NULL || VARSIZE(cache) != VARSIZE(query) || memcmp( cache, query, VARSIZE(query) ) !=0  )
+	{
+		qtrg = generate_trgm(VARDATA(query), VARSIZE(query) - VARHDRSZ);    
+
+		if (cache)
+			pfree(cache);
+
+		fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
+							MAXALIGN(VARSIZE(query)) + VARSIZE(qtrg) );
+		cache = (char*) fcinfo->flinfo->fn_extra;
+
+		memcpy( cache, query, VARSIZE(query) );
+		memcpy( cache + MAXALIGN(VARSIZE(query)), qtrg, VARSIZE(qtrg) );
+	}
+
+	qtrg = (TRGM*)( cache + MAXALIGN(VARSIZE(query)) );
+
 	if (GIST_LEAF(entry))
 	{							/* all leafs contains orig trgm */
 		float4		tmpsml = cnt_sml(key, qtrg);
-- 
GitLab