@@ -14,6 +14,7 @@ PG_FUNCTION_INFO_V1(gin_extract_trgm);
14
14
PG_FUNCTION_INFO_V1 (gin_extract_value_trgm );
15
15
PG_FUNCTION_INFO_V1 (gin_extract_query_trgm );
16
16
PG_FUNCTION_INFO_V1 (gin_trgm_consistent );
17
+ PG_FUNCTION_INFO_V1 (gin_trgm_triconsistent );
17
18
18
19
/*
19
20
* 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)
235
236
236
237
PG_RETURN_BOOL (res );
237
238
}
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
+ }