*** a/contrib/pg_trgm/pg_trgm--1.0.sql
--- b/contrib/pg_trgm/pg_trgm--1.0.sql
***************
*** 148,153 **** RETURNS bool
--- 148,158 ----
  AS 'MODULE_PATHNAME'
  LANGUAGE C IMMUTABLE STRICT;
  
+ CREATE FUNCTION gin_trgm_compare_partial(int4, int4, int2, internal)
+ RETURNS int
+ AS 'MODULE_PATHNAME'
+ LANGUAGE C IMMUTABLE STRICT;
+ 
  -- create the operator class for gin
  CREATE OPERATOR CLASS gin_trgm_ops
  FOR TYPE text USING gin
***************
*** 157,162 **** AS
--- 162,168 ----
          FUNCTION        2       gin_extract_value_trgm (text, internal),
          FUNCTION        3       gin_extract_query_trgm (text, internal, int2, internal, internal, internal, internal),
          FUNCTION        4       gin_trgm_consistent (internal, int2, text, int4, internal, internal, internal, internal),
+ 				FUNCTION        5       gin_trgm_compare_partial (int4, int4, int2, internal),
          STORAGE         int4;
  
  -- Add operators that are new in 9.1.
*** a/contrib/pg_trgm/trgm.h
--- b/contrib/pg_trgm/trgm.h
***************
*** 42,47 **** typedef char trgm[3];
--- 42,49 ----
  	*(((char*)(a))+2) = *(((char*)(b))+2);	\
  } while(0);
  
+ #define TRGMCHARLEN(t) ( (*(((char*)(t))+2)=='\0') ? ( (*(((char*)(t))+1)=='\0') ? 1 : 2) : 3 )
+ 
  uint32		trgm2int(trgm *ptr);
  
  #ifdef KEEPONLYALNUM
***************
*** 100,105 **** typedef char *BITVECP;
--- 102,108 ----
  #define ARRNELEM(x) ( ( VARSIZE(x) - TRGMHDRSIZE )/sizeof(trgm) )
  
  extern float4 trgm_limit;
+ extern bool	trgm_pmatch;
  
  TRGM	   *generate_trgm(char *str, int slen);
  TRGM	   *generate_wildcard_trgm(const char *str, int slen);
*** a/contrib/pg_trgm/trgm_gin.c
--- b/contrib/pg_trgm/trgm_gin.c
***************
*** 21,26 **** Datum		gin_extract_query_trgm(PG_FUNCTION_ARGS);
--- 21,29 ----
  PG_FUNCTION_INFO_V1(gin_trgm_consistent);
  Datum		gin_trgm_consistent(PG_FUNCTION_ARGS);
  
+ PG_FUNCTION_INFO_V1(gin_trgm_compare_partial);
+ Datum		gin_trgm_compare_partial(PG_FUNCTION_ARGS);
+ 
  /*
   * This function can only be called if a pre-9.1 version of the GIN operator
   * class definition is present in the catalogs (probably as a consequence
***************
*** 46,51 **** gin_extract_value_trgm(PG_FUNCTION_ARGS)
--- 49,57 ----
  	TRGM	   *trg;
  	int32		trglen;
  
+ #ifdef KEEPONLYALNUM
+ 	trgm_pmatch = true;
+ #endif
  	*nentries = 0;
  
  	trg = generate_trgm(VARDATA(val), VARSIZE(val) - VARHDRSZ);
***************
*** 79,86 **** gin_extract_query_trgm(PG_FUNCTION_ARGS)
  	int32	   *nentries = (int32 *) PG_GETARG_POINTER(1);
  	StrategyNumber strategy = PG_GETARG_UINT16(2);
  
! 	/* bool   **pmatch = (bool **) PG_GETARG_POINTER(3); */
! 	/* Pointer	  *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
  	/* bool   **nullFlags = (bool **) PG_GETARG_POINTER(5); */
  	int32	   *searchMode = (int32 *) PG_GETARG_POINTER(6);
  	Datum	   *entries = NULL;
--- 85,92 ----
  	int32	   *nentries = (int32 *) PG_GETARG_POINTER(1);
  	StrategyNumber strategy = PG_GETARG_UINT16(2);
  
! 	bool   **pmatch = (bool **) PG_GETARG_POINTER(3);
! 	Pointer	  **extra_data = (Pointer **) PG_GETARG_POINTER(4);
  	/* bool   **nullFlags = (bool **) PG_GETARG_POINTER(5); */
  	int32	   *searchMode = (int32 *) PG_GETARG_POINTER(6);
  	Datum	   *entries = NULL;
***************
*** 89,94 **** gin_extract_query_trgm(PG_FUNCTION_ARGS)
--- 95,104 ----
  	trgm	   *ptr;
  	int32		i;
  
+ #ifdef KEEPONLYALNUM
+ 	trgm_pmatch = true;
+ #endif
+ 
  	switch (strategy)
  	{
  		case SimilarityStrategyNumber:
***************
*** 115,120 **** gin_extract_query_trgm(PG_FUNCTION_ARGS)
--- 125,132 ----
  
  	trglen = ARRNELEM(trg);
  	*nentries = trglen;
+ 	*pmatch = NULL;
+ 	*extra_data = NULL;
  
  	if (trglen > 0)
  	{
***************
*** 124,129 **** gin_extract_query_trgm(PG_FUNCTION_ARGS)
--- 136,159 ----
  		{
  			int32		item = trgm2int(ptr);
  
+ #ifdef KEEPONLYALNUM
+ 			if (trgm_pmatch)
+ 			{
+ 				int		trgmcharlen = TRGMCHARLEN(ptr);
+ 
+ 				if (trgmcharlen < 3)
+ 				{
+ 					if (*pmatch == NULL)
+ 					{
+ 						*pmatch = (bool *) palloc0(sizeof(bool) * trglen);
+ 						*extra_data = (Pointer *) palloc0(sizeof(int) * trglen);
+ 					}
+ 					*(*pmatch + i) = true;
+ 					*((int *)(*extra_data + i)) = trgmcharlen;
+ 				}
+ 			}
+ #endif
+ 
  			entries[i] = Int32GetDatum(item);
  			ptr++;
  		}
***************
*** 197,199 **** gin_trgm_consistent(PG_FUNCTION_ARGS)
--- 227,245 ----
  
  	PG_RETURN_BOOL(res);
  }
+ 
+ Datum
+ gin_trgm_compare_partial(PG_FUNCTION_ARGS)
+ {
+ 	int32		a = PG_GETARG_INT32(0);
+ 	int32		b = PG_GETARG_INT32(1);
+ 	int32		shiftlen = (3 - PG_GETARG_INT32(3)) * 8;
+ 
+ 	a >>= shiftlen;
+ 	b >>= shiftlen;
+ 
+ 	if (a == b)
+ 		PG_RETURN_INT32(0);
+ 	else
+ 		PG_RETURN_INT32(1);
+ }
*** a/contrib/pg_trgm/trgm_op.c
--- b/contrib/pg_trgm/trgm_op.c
***************
*** 15,20 **** PG_MODULE_MAGIC;
--- 15,22 ----
  
  float4		trgm_limit = 0.3f;
  
+ bool		trgm_pmatch = false;
+ 
  PG_FUNCTION_INFO_V1(set_limit);
  Datum		set_limit(PG_FUNCTION_ARGS);
  
***************
*** 142,148 **** make_trigrams(trgm *tptr, char *str, int bytelen, int charlen)
--- 144,163 ----
  	char	   *ptr = str;
  
  	if (charlen < 3)
+ 	{
+ #ifdef KEEPONLYALNUM
+ 		if (trgm_pmatch)
+ 		{
+ 			int		i;
+ 
+ 			Assert(bytelen == charlen);
+ 			for (i = 0; i < 3; i++)
+ 				*(((char *)tptr) + i) = (i < bytelen) ? *(ptr + i) : '\0';
+ 			tptr++;
+ 		}
+ #endif
  		return tptr;
+ 	}
  
  #ifdef USE_WIDE_UPPER_LOWER
  	if (pg_database_encoding_max_length() > 1)
