Skip to content

Commit 97f3014

Browse files
committed
This supports the triconsistent function for pg_trgm GIN opclass
to make it faster to implement indexed queries where some keys are common and some are rare. Patch by Jeff Janes
1 parent 1a51180 commit 97f3014

File tree

5 files changed

+117
-3
lines changed

5 files changed

+117
-3
lines changed

contrib/pg_trgm/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ MODULE_big = pg_trgm
44
OBJS = trgm_op.o trgm_gist.o trgm_gin.o trgm_regexp.o $(WIN32RES)
55

66
EXTENSION = pg_trgm
7-
DATA = pg_trgm--1.1.sql pg_trgm--1.0--1.1.sql pg_trgm--unpackaged--1.0.sql
7+
DATA = pg_trgm--1.2.sql pg_trgm--1.0--1.1.sql pg_trgm--1.1--1.2.sql pg_trgm--unpackaged--1.0.sql
88
PGFILEDESC = "pg_trgm - trigram matching"
99

1010
REGRESS = pg_trgm

contrib/pg_trgm/pg_trgm--1.1--1.2.sql

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/* contrib/pg_trgm/pg_trgm--1.1--1.2.sql */
2+
3+
-- complain if script is sourced in psql, rather than via ALTER EXTENSION
4+
\echo Use "ALTER EXTENSION pg_trgm UPDATE TO '1.2'" to load this file. \quit
5+
6+
CREATE FUNCTION gin_trgm_triconsistent(internal, int2, text, int4, internal, internal, internal)
7+
RETURNS "char"
8+
AS 'MODULE_PATHNAME'
9+
LANGUAGE C IMMUTABLE STRICT;
10+
11+
ALTER OPERATOR FAMILY gin_trgm_ops USING gin ADD
12+
FUNCTION 6 (text, text) gin_trgm_triconsistent (internal, int2, text, int4, internal, internal, internal);

contrib/pg_trgm/pg_trgm--1.1.sql renamed to contrib/pg_trgm/pg_trgm--1.2.sql

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* contrib/pg_trgm/pg_trgm--1.1.sql */
1+
/* contrib/pg_trgm/pg_trgm--1.2.sql */
22

33
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
44
\echo Use "CREATE EXTENSION pg_trgm" to load this file. \quit
@@ -176,3 +176,13 @@ ALTER OPERATOR FAMILY gin_trgm_ops USING gin ADD
176176
ALTER OPERATOR FAMILY gin_trgm_ops USING gin ADD
177177
OPERATOR 5 pg_catalog.~ (text, text),
178178
OPERATOR 6 pg_catalog.~* (text, text);
179+
180+
-- Add functions that are new in 9.6 (pg_trgm 1.2).
181+
182+
CREATE FUNCTION gin_trgm_triconsistent(internal, int2, text, int4, internal, internal, internal)
183+
RETURNS "char"
184+
AS 'MODULE_PATHNAME'
185+
LANGUAGE C IMMUTABLE STRICT;
186+
187+
ALTER OPERATOR FAMILY gin_trgm_ops USING gin ADD
188+
FUNCTION 6 (text,text) gin_trgm_triconsistent (internal, int2, text, int4, internal, internal, internal);

contrib/pg_trgm/pg_trgm.control

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# pg_trgm extension
22
comment = 'text similarity measurement and index searching based on trigrams'
3-
default_version = '1.1'
3+
default_version = '1.2'
44
module_pathname = '$libdir/pg_trgm'
55
relocatable = true

contrib/pg_trgm/trgm_gin.c

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ PG_FUNCTION_INFO_V1(gin_extract_trgm);
1414
PG_FUNCTION_INFO_V1(gin_extract_value_trgm);
1515
PG_FUNCTION_INFO_V1(gin_extract_query_trgm);
1616
PG_FUNCTION_INFO_V1(gin_trgm_consistent);
17+
PG_FUNCTION_INFO_V1(gin_trgm_triconsistent);
1718

1819
/*
1920
* This function can only be called if a pre-9.1 version of the GIN operator
@@ -235,3 +236,94 @@ gin_trgm_consistent(PG_FUNCTION_ARGS)
235236

236237
PG_RETURN_BOOL(res);
237238
}
239+
240+
/*
241+
* In all cases, GIN_TRUE is at least as favorable to inclusion as
242+
* GIN_MAYBE. If no better option is available, simply treat
243+
* GIN_MAYBE as if it were GIN_TRUE and apply the same test as the binary
244+
* consistent function.
245+
*/
246+
Datum
247+
gin_trgm_triconsistent(PG_FUNCTION_ARGS)
248+
{
249+
GinTernaryValue *check = (GinTernaryValue *) PG_GETARG_POINTER(0);
250+
StrategyNumber strategy = PG_GETARG_UINT16(1);
251+
252+
/* text *query = PG_GETARG_TEXT_P(2); */
253+
int32 nkeys = PG_GETARG_INT32(3);
254+
Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4);
255+
GinTernaryValue res = GIN_MAYBE;
256+
int32 i,
257+
ntrue;
258+
bool *boolcheck;
259+
260+
switch (strategy)
261+
{
262+
case SimilarityStrategyNumber:
263+
/* Count the matches */
264+
ntrue = 0;
265+
for (i = 0; i < nkeys; i++)
266+
{
267+
if (check[i] != GIN_FALSE)
268+
ntrue++;
269+
}
270+
#ifdef DIVUNION
271+
res = (nkeys == ntrue) ? GIN_MAYBE : (((((float4) ntrue) / ((float4) (nkeys - ntrue))) >= trgm_limit) ? GIN_MAYBE : GIN_FALSE);
272+
#else
273+
res = (nkeys == 0) ? GIN_FALSE : (((((float4) ntrue) / ((float4) nkeys)) >= trgm_limit) ? GIN_MAYBE : GIN_FALSE);
274+
#endif
275+
break;
276+
case ILikeStrategyNumber:
277+
#ifndef IGNORECASE
278+
elog(ERROR, "cannot handle ~~* with case-sensitive trigrams");
279+
#endif
280+
/* FALL THRU */
281+
case LikeStrategyNumber:
282+
/* Check if all extracted trigrams are presented. */
283+
res = GIN_MAYBE;
284+
for (i = 0; i < nkeys; i++)
285+
{
286+
if (check[i] == GIN_FALSE)
287+
{
288+
res = GIN_FALSE;
289+
break;
290+
}
291+
}
292+
break;
293+
case RegExpICaseStrategyNumber:
294+
#ifndef IGNORECASE
295+
elog(ERROR, "cannot handle ~* with case-sensitive trigrams");
296+
#endif
297+
/* FALL THRU */
298+
case RegExpStrategyNumber:
299+
if (nkeys < 1)
300+
{
301+
/* Regex processing gave no result: do full index scan */
302+
res = GIN_MAYBE;
303+
}
304+
else
305+
{
306+
/*
307+
* As trigramsMatchGraph implements a montonic boolean function,
308+
* promoting all GIN_MAYBE keys to GIN_TRUE will give a
309+
* conservative result.
310+
*/
311+
boolcheck = (bool *) palloc(sizeof(bool) * nkeys);
312+
for (i = 0; i < nkeys; i++)
313+
boolcheck[i] = (check[i] != GIN_FALSE);
314+
if (!trigramsMatchGraph((TrgmPackedGraph *) extra_data[0],
315+
boolcheck))
316+
res = GIN_FALSE;
317+
pfree(boolcheck);
318+
}
319+
break;
320+
default:
321+
elog(ERROR, "unrecognized strategy number: %d", strategy);
322+
res = GIN_FALSE; /* keep compiler quiet */
323+
break;
324+
}
325+
326+
/* All cases served by this function are inexact */
327+
Assert(res != GIN_TRUE);
328+
PG_RETURN_GIN_TERNARY_VALUE(res);
329+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy