@@ -14,6 +14,7 @@ PG_FUNCTION_INFO_V1(gin_extract_trgm);
1414PG_FUNCTION_INFO_V1 (gin_extract_value_trgm );
1515PG_FUNCTION_INFO_V1 (gin_extract_query_trgm );
1616PG_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