LCOV - differential code coverage report
Current view: top level - contrib/pg_trgm - trgm_gist.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 79.7 % 429 342 4 20 51 12 20 189 3 130 54 187 1 5
Current Date: 2023-04-08 17:13:01 Functions: 87.5 % 32 28 4 28 4 27 1
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (60,120] days: 42.9 % 7 3 4 3
Legend: Lines: hit not hit (240..) days: 80.3 % 422 339 20 51 12 20 189 130 54 185
Function coverage date bins:
(240..) days: 44.4 % 63 28 4 28 4 27

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*
                                  2                 :  * contrib/pg_trgm/trgm_gist.c
                                  3                 :  */
                                  4                 : #include "postgres.h"
                                  5                 : 
                                  6                 : #include "access/reloptions.h"
                                  7                 : #include "access/stratnum.h"
                                  8                 : #include "fmgr.h"
                                  9                 : #include "port/pg_bitutils.h"
                                 10                 : #include "trgm.h"
                                 11                 : #include "varatt.h"
                                 12                 : 
                                 13                 : /* gist_trgm_ops opclass options */
                                 14                 : typedef struct
                                 15                 : {
                                 16                 :     int32       vl_len_;        /* varlena header (do not touch directly!) */
                                 17                 :     int         siglen;         /* signature length in bytes */
                                 18                 : } TrgmGistOptions;
                                 19                 : 
                                 20                 : #define GET_SIGLEN()            (PG_HAS_OPCLASS_OPTIONS() ? \
                                 21                 :                                  ((TrgmGistOptions *) PG_GET_OPCLASS_OPTIONS())->siglen : \
                                 22                 :                                  SIGLEN_DEFAULT)
                                 23                 : 
                                 24                 : typedef struct
                                 25                 : {
                                 26                 :     /* most recent inputs to gtrgm_consistent */
                                 27                 :     StrategyNumber strategy;
                                 28                 :     text       *query;
                                 29                 :     /* extracted trigrams for query */
                                 30                 :     TRGM       *trigrams;
                                 31                 :     /* if a regex operator, the extracted graph */
                                 32                 :     TrgmPackedGraph *graph;
                                 33                 : 
                                 34                 :     /*
                                 35                 :      * The "query" and "trigrams" are stored in the same palloc block as this
                                 36                 :      * cache struct, at MAXALIGN'ed offsets.  The graph however isn't.
                                 37                 :      */
                                 38                 : } gtrgm_consistent_cache;
                                 39                 : 
                                 40                 : #define GETENTRY(vec,pos) ((TRGM *) DatumGetPointer((vec)->vector[(pos)].key))
                                 41                 : 
                                 42                 : 
 6887 teodor                     43 GIC           1 : PG_FUNCTION_INFO_V1(gtrgm_in);
 6887 teodor                     44 CBC           1 : PG_FUNCTION_INFO_V1(gtrgm_out);
                                 45               4 : PG_FUNCTION_INFO_V1(gtrgm_compress);
                                 46               4 : PG_FUNCTION_INFO_V1(gtrgm_decompress);
                                 47               4 : PG_FUNCTION_INFO_V1(gtrgm_consistent);
 4509 tgl                        48               4 : PG_FUNCTION_INFO_V1(gtrgm_distance);
 6887 teodor                     49               4 : PG_FUNCTION_INFO_V1(gtrgm_union);
                                 50               4 : PG_FUNCTION_INFO_V1(gtrgm_same);
                                 51               4 : PG_FUNCTION_INFO_V1(gtrgm_penalty);
                                 52               4 : PG_FUNCTION_INFO_V1(gtrgm_picksplit);
 1105 akorotkov                  53               4 : PG_FUNCTION_INFO_V1(gtrgm_options);
 6887 teodor                     54 ECB             : 
                                 55                 : 
                                 56                 : Datum
 6887 teodor                     57 UIC           0 : gtrgm_in(PG_FUNCTION_ARGS)
 6887 teodor                     58 EUB             : {
  120 tgl                        59 UNC           0 :     ereport(ERROR,
                                 60                 :             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                 61                 :              errmsg("cannot accept a value of type %s", "gtrgm")));
                                 62                 : 
                                 63                 :     PG_RETURN_VOID();           /* keep compiler quiet */
                                 64                 : }
                                 65                 : 
                                 66                 : Datum
 6887 teodor                     67 UIC           0 : gtrgm_out(PG_FUNCTION_ARGS)
                                 68                 : {
  120 tgl                        69 UNC           0 :     ereport(ERROR,
                                 70                 :             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                 71                 :              errmsg("cannot display a value of type %s", "gtrgm")));
                                 72                 : 
                                 73                 :     PG_RETURN_VOID();           /* keep compiler quiet */
 6887 teodor                     74 EUB             : }
                                 75                 : 
 1105 akorotkov                  76                 : static TRGM *
 1105 akorotkov                  77 GIC       26625 : gtrgm_alloc(bool isalltrue, int siglen, BITVECP sign)
                                 78                 : {
                                 79           26625 :     int         flag = SIGNKEY | (isalltrue ? ALLISTRUE : 0);
                                 80           26625 :     int         size = CALCGTSIZE(flag, siglen);
                                 81           26625 :     TRGM       *res = palloc(size);
                                 82                 : 
                                 83           26625 :     SET_VARSIZE(res, size);
 1105 akorotkov                  84 CBC       26625 :     res->flag = flag;
                                 85                 : 
                                 86           26625 :     if (!isalltrue)
 1105 akorotkov                  87 ECB             :     {
 1105 akorotkov                  88 CBC       26625 :         if (sign)
 1105 akorotkov                  89 GIC         536 :             memcpy(GETSIGN(res), sign, siglen);
 1105 akorotkov                  90 ECB             :         else
 1105 akorotkov                  91 CBC       26089 :             memset(GETSIGN(res), 0, siglen);
                                 92                 :     }
 1105 akorotkov                  93 ECB             : 
 1105 akorotkov                  94 GIC       26625 :     return res;
 1105 akorotkov                  95 ECB             : }
                                 96                 : 
                                 97                 : static void
 1105 akorotkov                  98 CBC       45790 : makesign(BITVECP sign, TRGM *a, int siglen)
                                 99                 : {
                                100                 :     int32       k,
 6887 teodor                    101           45790 :                 len = ARRNELEM(a);
 6887 teodor                    102 GIC       45790 :     trgm       *ptr = GETARR(a);
 3940 peter_e                   103           45790 :     int32       tmp = 0;
                                104                 : 
   61 peter                     105 GNC       45790 :     MemSet(sign, 0, siglen);
 1105 akorotkov                 106 GIC       45790 :     SETBIT(sign, SIGLENBIT(siglen));    /* set last unused bit */
 6797 bruce                     107          443775 :     for (k = 0; k < len; k++)
 6797 bruce                     108 ECB             :     {
 6797 bruce                     109 CBC      397985 :         CPTRGM(((char *) &tmp), ptr + k);
 1105 akorotkov                 110          397985 :         HASH(sign, tmp, siglen);
                                111                 :     }
 6887 teodor                    112           45790 : }
 6887 teodor                    113 ECB             : 
                                114                 : Datum
 6887 teodor                    115 GIC       25533 : gtrgm_compress(PG_FUNCTION_ARGS)
 6887 teodor                    116 ECB             : {
 6887 teodor                    117 CBC       25533 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
  878 akorotkov                 118 GIC       25533 :     int         siglen = GET_SIGLEN();
 6887 teodor                    119 CBC       25533 :     GISTENTRY  *retval = entry;
                                120                 : 
 6887 teodor                    121 GIC       25533 :     if (entry->leafkey)
 6887 teodor                    122 ECB             :     {                           /* trgm */
                                123                 :         TRGM       *res;
 2219 noah                      124 CBC       23402 :         text       *val = DatumGetTextPP(entry->key);
 6887 teodor                    125 ECB             : 
 2219 noah                      126 CBC       23402 :         res = generate_trgm(VARDATA_ANY(val), VARSIZE_ANY_EXHDR(val));
 6887 teodor                    127 GIC       23402 :         retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
 6887 teodor                    128 CBC       23402 :         gistentryinit(*retval, PointerGetDatum(res),
                                129                 :                       entry->rel, entry->page,
                                130                 :                       entry->offset, false);
 6887 teodor                    131 ECB             :     }
 6887 teodor                    132 GIC        2131 :     else if (ISSIGNKEY(DatumGetPointer(entry->key)) &&
 6887 teodor                    133 CBC        2131 :              !ISALLTRUE(DatumGetPointer(entry->key)))
 6887 teodor                    134 ECB             :     {
 1105 akorotkov                 135                 :         int32       i;
                                136                 :         TRGM       *res;
 6887 teodor                    137 GIC        2131 :         BITVECP     sign = GETSIGN(DatumGetPointer(entry->key));
                                138                 : 
 1105 akorotkov                 139 CBC        2288 :         LOOPBYTE(siglen)
 5623 bruce                     140 ECB             :         {
 5623 bruce                     141 GIC        2288 :             if ((sign[i] & 0xff) != 0xff)
                                142            2131 :                 PG_RETURN_POINTER(retval);
                                143                 :         }
 6887 teodor                    144 ECB             : 
 1105 akorotkov                 145 UIC           0 :         res = gtrgm_alloc(true, siglen, sign);
 6887 teodor                    146 LBC           0 :         retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
 6887 teodor                    147 UIC           0 :         gistentryinit(*retval, PointerGetDatum(res),
 6887 teodor                    148 ECB             :                       entry->rel, entry->page,
 2062 peter_e                   149                 :                       entry->offset, false);
                                150                 :     }
 6887 teodor                    151 GIC       23402 :     PG_RETURN_POINTER(retval);
 6887 teodor                    152 EUB             : }
                                153                 : 
                                154                 : Datum
 6887 teodor                    155 GIC     1374372 : gtrgm_decompress(PG_FUNCTION_ARGS)
                                156                 : {
 5847 tgl                       157         1374372 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
 5847 tgl                       158 ECB             :     GISTENTRY  *retval;
                                159                 :     text       *key;
                                160                 : 
 2219 noah                      161 GIC     1374372 :     key = DatumGetTextPP(entry->key);
 5847 tgl                       162 ECB             : 
 5847 tgl                       163 GIC     1374372 :     if (key != (text *) DatumGetPointer(entry->key))
 5847 tgl                       164 ECB             :     {
                                165                 :         /* need to pass back the decompressed item */
 5847 tgl                       166 UIC           0 :         retval = palloc(sizeof(GISTENTRY));
                                167               0 :         gistentryinit(*retval, PointerGetDatum(key),
 5847 tgl                       168 ECB             :                       entry->rel, entry->page, entry->offset, entry->leafkey);
 5847 tgl                       169 UIC           0 :         PG_RETURN_POINTER(retval);
 5847 tgl                       170 ECB             :     }
                                171                 :     else
                                172                 :     {
 5847 tgl                       173 EUB             :         /* we can return the entry as-is */
 5847 tgl                       174 GBC     1374372 :         PG_RETURN_POINTER(entry);
                                175                 :     }
 6887 teodor                    176 EUB             : }
                                177                 : 
                                178                 : static int32
 1105 akorotkov                 179 GIC         643 : cnt_sml_sign_common(TRGM *qtrg, BITVECP sign, int siglen)
                                180                 : {
 3940 peter_e                   181 CBC         643 :     int32       count = 0;
                                182                 :     int32       k,
 4509 tgl                       183 GIC         643 :                 len = ARRNELEM(qtrg);
                                184             643 :     trgm       *ptr = GETARR(qtrg);
 3940 peter_e                   185             643 :     int32       tmp = 0;
 4509 tgl                       186 ECB             : 
 4509 tgl                       187 GIC        5860 :     for (k = 0; k < len; k++)
 4509 tgl                       188 ECB             :     {
 4509 tgl                       189 GIC        5217 :         CPTRGM(((char *) &tmp), ptr + k);
 1105 akorotkov                 190 CBC        5217 :         count += GETBIT(sign, HASHVAL(tmp, siglen));
 4509 tgl                       191 ECB             :     }
                                192                 : 
 4509 tgl                       193 GIC         643 :     return count;
 4509 tgl                       194 ECB             : }
                                195                 : 
 6887 teodor                    196                 : Datum
 6887 teodor                    197 CBC       38288 : gtrgm_consistent(PG_FUNCTION_ARGS)
                                198                 : {
 5473 tgl                       199 GIC       38288 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
 5473 tgl                       200 CBC       38288 :     text       *query = PG_GETARG_TEXT_P(1);
 4509 tgl                       201 GIC       38288 :     StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
                                202                 : 
                                203                 :     /* Oid      subtype = PG_GETARG_OID(3); */
 5473 tgl                       204 CBC       38288 :     bool       *recheck = (bool *) PG_GETARG_POINTER(4);
  878 akorotkov                 205 GIC       38288 :     int         siglen = GET_SIGLEN();
 5473 tgl                       206 CBC       38288 :     TRGM       *key = (TRGM *) DatumGetPointer(entry->key);
 5385 teodor                    207 ECB             :     TRGM       *qtrg;
 4509 tgl                       208                 :     bool        res;
 4209 tgl                       209 GIC       38288 :     Size        querysize = VARSIZE(query);
                                210                 :     gtrgm_consistent_cache *cache;
 2580 teodor                    211 ECB             :     double      nlimit;
 4451 tgl                       212                 : 
                                213                 :     /*
                                214                 :      * We keep the extracted trigrams in cache, because trigram extraction is
                                215                 :      * relatively CPU-expensive.  When trying to reuse a cached value, check
 3651                           216                 :      * strategy number not just query itself, because trigram extraction
                                217                 :      * depends on strategy.
                                218                 :      *
                                219                 :      * The cached structure is a single palloc chunk containing the
                                220                 :      * gtrgm_consistent_cache header, then the input query (4-byte length
                                221                 :      * word, uncompressed, starting at a MAXALIGN boundary), then the TRGM
                                222                 :      * value (also starting at a MAXALIGN boundary).  However we don't try to
                                223                 :      * include the regex graph (if any) in that struct.  (XXX currently, this
                                224                 :      * approach can leak regex graphs across index rescans.  Not clear if
                                225                 :      * that's worth fixing.)
                                226                 :      */
 3651 tgl                       227 GIC       38288 :     cache = (gtrgm_consistent_cache *) fcinfo->flinfo->fn_extra;
 4209                           228           38288 :     if (cache == NULL ||
 3651                           229           38232 :         cache->strategy != strategy ||
                                230           38232 :         VARSIZE(cache->query) != querysize ||
                                231           38232 :         memcmp((char *) cache->query, (char *) query, querysize) != 0)
                                232                 :     {
                                233                 :         gtrgm_consistent_cache *newcache;
 3651 tgl                       234 CBC          56 :         TrgmPackedGraph *graph = NULL;
 3651 tgl                       235 ECB             :         Size        qtrgsize;
 4209                           236                 : 
 4451 tgl                       237 CBC          56 :         switch (strategy)
 4451 tgl                       238 ECB             :         {
 4451 tgl                       239 GIC          28 :             case SimilarityStrategyNumber:
                                240                 :             case WordSimilarityStrategyNumber:
 1845 teodor                    241 ECB             :             case StrictWordSimilarityStrategyNumber:
                                242                 :             case EqualStrategyNumber:
 4209 tgl                       243 GIC          28 :                 qtrg = generate_trgm(VARDATA(query),
 4209 tgl                       244 CBC          28 :                                      querysize - VARHDRSZ);
 4451 tgl                       245 GIC          28 :                 break;
 4451 tgl                       246 CBC           7 :             case ILikeStrategyNumber:
                                247                 : #ifndef IGNORECASE
                                248                 :                 elog(ERROR, "cannot handle ~~* with case-sensitive trigrams");
                                249                 : #endif
 4451 tgl                       250 ECB             :                 /* FALL THRU */
                                251                 :             case LikeStrategyNumber:
 4209 tgl                       252 CBC           7 :                 qtrg = generate_wildcard_trgm(VARDATA(query),
                                253               7 :                                               querysize - VARHDRSZ);
 4451 tgl                       254 GIC           7 :                 break;
 3651                           255              21 :             case RegExpICaseStrategyNumber:
                                256                 : #ifndef IGNORECASE
                                257                 :                 elog(ERROR, "cannot handle ~* with case-sensitive trigrams");
                                258                 : #endif
 3651 tgl                       259 ECB             :                 /* FALL THRU */
                                260                 :             case RegExpStrategyNumber:
 3651 tgl                       261 CBC          21 :                 qtrg = createTrgmNFA(query, PG_GET_COLLATION(),
                                262              21 :                                      &graph, fcinfo->flinfo->fn_mcxt);
                                263                 :                 /* just in case an empty array is returned ... */
 3651 tgl                       264 GIC          21 :                 if (qtrg && ARRNELEM(qtrg) <= 0)
                                265                 :                 {
 3651 tgl                       266 UIC           0 :                     pfree(qtrg);
                                267               0 :                     qtrg = NULL;
 3651 tgl                       268 ECB             :                 }
 3651 tgl                       269 CBC          21 :                 break;
 4451 tgl                       270 UIC           0 :             default:
 4451 tgl                       271 LBC           0 :                 elog(ERROR, "unrecognized strategy number: %d", strategy);
                                272                 :                 qtrg = NULL;    /* keep compiler quiet */
 4451 tgl                       273 EUB             :                 break;
                                274                 :         }
                                275                 : 
 3651 tgl                       276 CBC          56 :         qtrgsize = qtrg ? VARSIZE(qtrg) : 0;
 3651 tgl                       277 EUB             : 
                                278                 :         newcache = (gtrgm_consistent_cache *)
 3651 tgl                       279 GIC          56 :             MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
                                280                 :                                MAXALIGN(sizeof(gtrgm_consistent_cache)) +
                                281              56 :                                MAXALIGN(querysize) +
                                282                 :                                qtrgsize);
 4209 tgl                       283 ECB             : 
 3651 tgl                       284 GIC          56 :         newcache->strategy = strategy;
                                285              56 :         newcache->query = (text *)
 3651 tgl                       286 ECB             :             ((char *) newcache + MAXALIGN(sizeof(gtrgm_consistent_cache)));
 3651 tgl                       287 GIC          56 :         memcpy((char *) newcache->query, (char *) query, querysize);
 3651 tgl                       288 CBC          56 :         if (qtrg)
                                289                 :         {
 3651 tgl                       290 GIC          52 :             newcache->trigrams = (TRGM *)
 3651 tgl                       291 CBC          52 :                 ((char *) newcache->query + MAXALIGN(querysize));
                                292              52 :             memcpy((char *) newcache->trigrams, (char *) qtrg, qtrgsize);
                                293                 :             /* release qtrg in case it was made in fn_mcxt */
                                294              52 :             pfree(qtrg);
 3651 tgl                       295 ECB             :         }
                                296                 :         else
 3651 tgl                       297 CBC           4 :             newcache->trigrams = NULL;
                                298              56 :         newcache->graph = graph;
 4209 tgl                       299 ECB             : 
 5385 teodor                    300 GIC          56 :         if (cache)
 5385 teodor                    301 LBC           0 :             pfree(cache);
 3651 tgl                       302 GIC          56 :         fcinfo->flinfo->fn_extra = (void *) newcache;
                                303              56 :         cache = newcache;
 5385 teodor                    304 ECB             :     }
                                305                 : 
 3651 tgl                       306 GIC       38288 :     qtrg = cache->trigrams;
 5385 teodor                    307 ECB             : 
 4509 tgl                       308 GBC       38288 :     switch (strategy)
 4509 tgl                       309 ECB             :     {
 4509 tgl                       310 CBC       35887 :         case SimilarityStrategyNumber:
                                311                 :         case WordSimilarityStrategyNumber:
                                312                 :         case StrictWordSimilarityStrategyNumber:
 1809 tgl                       313 ECB             : 
                                314                 :             /*
                                315                 :              * Similarity search is exact. (Strict) word similarity search is
                                316                 :              * inexact
                                317                 :              */
 1845 teodor                    318 GIC       35887 :             *recheck = (strategy != SimilarityStrategyNumber);
                                319                 : 
                                320           35887 :             nlimit = index_strategy_get_limit(strategy);
                                321                 : 
 4509 tgl                       322           35887 :             if (GIST_LEAF(entry))
                                323                 :             {                   /* all leafs contains orig trgm */
 2484                           324           35282 :                 double      tmpsml = cnt_sml(qtrg, key, *recheck);
 2495 rhaas                     325 ECB             : 
 2484 tgl                       326 GIC       35282 :                 res = (tmpsml >= nlimit);
 4509 tgl                       327 ECB             :             }
 4509 tgl                       328 GIC         605 :             else if (ISALLTRUE(key))
 4382 bruce                     329 ECB             :             {                   /* non-leaf contains signature */
 4509 tgl                       330 UIC           0 :                 res = true;
 4509 tgl                       331 ECB             :             }
                                332                 :             else
 4382 bruce                     333                 :             {                   /* non-leaf contains signature */
 1105 akorotkov                 334 GIC         605 :                 int32       count = cnt_sml_sign_common(qtrg, GETSIGN(key), siglen);
 3940 peter_e                   335 CBC         605 :                 int32       len = ARRNELEM(qtrg);
                                336                 : 
 4509 tgl                       337 GBC         605 :                 if (len == 0)
 4509 tgl                       338 UIC           0 :                     res = false;
                                339                 :                 else
 2580 teodor                    340 GIC         605 :                     res = (((((float8) count) / ((float8) len))) >= nlimit);
 4509 tgl                       341 ECB             :             }
 4509 tgl                       342 CBC       35887 :             break;
 4451 tgl                       343 GIC         190 :         case ILikeStrategyNumber:
 4451 tgl                       344 ECB             : #ifndef IGNORECASE
 4451 tgl                       345 EUB             :             elog(ERROR, "cannot handle ~~* with case-sensitive trigrams");
                                346                 : #endif
 4451 tgl                       347 ECB             :             /* FALL THRU */
                                348                 :         case LikeStrategyNumber:
  875 akorotkov                 349                 :         case EqualStrategyNumber:
                                350                 :             /* Wildcard and equal search are inexact */
 4451 tgl                       351 GIC         190 :             *recheck = true;
                                352                 : 
                                353                 :             /*
                                354                 :              * Check if all the extracted trigrams can be present in child
                                355                 :              * nodes.
                                356                 :              */
                                357             190 :             if (GIST_LEAF(entry))
 4382 bruce                     358 ECB             :             {                   /* all leafs contains orig trgm */
 4451 tgl                       359 GIC         190 :                 res = trgm_contained_by(qtrg, key);
                                360                 :             }
 4451 tgl                       361 UIC           0 :             else if (ISALLTRUE(key))
                                362                 :             {                   /* non-leaf contains signature */
                                363               0 :                 res = true;
 4451 tgl                       364 ECB             :             }
                                365                 :             else
 4382 bruce                     366                 :             {                   /* non-leaf contains signature */
                                367                 :                 int32       k,
 4382 bruce                     368 UBC           0 :                             tmp = 0,
 4382 bruce                     369 UIC           0 :                             len = ARRNELEM(qtrg);
 4382 bruce                     370 UBC           0 :                 trgm       *ptr = GETARR(qtrg);
 4382 bruce                     371 UIC           0 :                 BITVECP     sign = GETSIGN(key);
                                372                 : 
 4451 tgl                       373               0 :                 res = true;
                                374               0 :                 for (k = 0; k < len; k++)
 4451 tgl                       375 EUB             :                 {
 4451 tgl                       376 UBC           0 :                     CPTRGM(((char *) &tmp), ptr + k);
 1105 akorotkov                 377               0 :                     if (!GETBIT(sign, HASHVAL(tmp, siglen)))
 4451 tgl                       378 EUB             :                     {
 4451 tgl                       379 UIC           0 :                         res = false;
 4451 tgl                       380 UBC           0 :                         break;
 4451 tgl                       381 EUB             :                     }
                                382                 :                 }
                                383                 :             }
 4451 tgl                       384 GBC         190 :             break;
 3651 tgl                       385 GIC        2211 :         case RegExpICaseStrategyNumber:
 3651 tgl                       386 EUB             : #ifndef IGNORECASE
                                387                 :             elog(ERROR, "cannot handle ~* with case-sensitive trigrams");
                                388                 : #endif
                                389                 :             /* FALL THRU */
                                390                 :         case RegExpStrategyNumber:
 3651 tgl                       391 ECB             :             /* Regexp search is inexact */
 3651 tgl                       392 CBC        2211 :             *recheck = true;
                                393                 : 
                                394                 :             /* Check regex match as much as we can with available info */
 3651 tgl                       395 GIC        2211 :             if (qtrg)
                                396                 :             {
                                397            2171 :                 if (GIST_LEAF(entry))
                                398                 :                 {               /* all leafs contains orig trgm */
 3651 tgl                       399 ECB             :                     bool       *check;
                                400                 : 
 3651 tgl                       401 GIC        2150 :                     check = trgm_presence_map(qtrg, key);
 3651 tgl                       402 CBC        2150 :                     res = trigramsMatchGraph(cache->graph, check);
 3651 tgl                       403 GIC        2150 :                     pfree(check);
 3651 tgl                       404 ECB             :                 }
 3651 tgl                       405 GIC          21 :                 else if (ISALLTRUE(key))
                                406                 :                 {               /* non-leaf contains signature */
 3651 tgl                       407 UIC           0 :                     res = true;
 3651 tgl                       408 ECB             :                 }
                                409                 :                 else
                                410                 :                 {               /* non-leaf contains signature */
                                411                 :                     int32       k,
 3651 tgl                       412 CBC          21 :                                 tmp = 0,
 3651 tgl                       413 GIC          21 :                                 len = ARRNELEM(qtrg);
 3651 tgl                       414 GBC          21 :                     trgm       *ptr = GETARR(qtrg);
 3651 tgl                       415 GIC          21 :                     BITVECP     sign = GETSIGN(key);
                                416                 :                     bool       *check;
                                417                 : 
                                418                 :                     /*
 3646 tgl                       419 ECB             :                      * GETBIT() tests may give false positives, due to limited
 3260 bruce                     420                 :                      * size of the sign array.  But since trigramsMatchGraph()
 3646 tgl                       421                 :                      * implements a monotone boolean function, false positives
                                422                 :                      * in the check array can't lead to false negative answer.
                                423                 :                      * So we can apply trigramsMatchGraph despite uncertainty,
                                424                 :                      * and that usefully improves the quality of the search.
                                425                 :                      */
 3646 tgl                       426 GIC          21 :                     check = (bool *) palloc(len * sizeof(bool));
 3651                           427            5313 :                     for (k = 0; k < len; k++)
                                428                 :                     {
                                429            5292 :                         CPTRGM(((char *) &tmp), ptr + k);
 1105 akorotkov                 430            5292 :                         check[k] = GETBIT(sign, HASHVAL(tmp, siglen));
                                431                 :                     }
 3646 tgl                       432              21 :                     res = trigramsMatchGraph(cache->graph, check);
 3646 tgl                       433 CBC          21 :                     pfree(check);
 3651 tgl                       434 ECB             :                 }
                                435                 :             }
                                436                 :             else
                                437                 :             {
                                438                 :                 /* trigram-free query must be rechecked everywhere */
 3651 tgl                       439 CBC          40 :                 res = true;
 3651 tgl                       440 ECB             :             }
 3651 tgl                       441 GIC        2211 :             break;
 4509 tgl                       442 UIC           0 :         default:
                                443               0 :             elog(ERROR, "unrecognized strategy number: %d", strategy);
                                444                 :             res = false;        /* keep compiler quiet */
                                445                 :             break;
 6797 bruce                     446 ECB             :     }
                                447                 : 
 4509 tgl                       448 CBC       38288 :     PG_RETURN_BOOL(res);
 4509 tgl                       449 EUB             : }
                                450                 : 
                                451                 : Datum
 4509 tgl                       452 GIC        3095 : gtrgm_distance(PG_FUNCTION_ARGS)
                                453                 : {
                                454            3095 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
 4509 tgl                       455 CBC        3095 :     text       *query = PG_GETARG_TEXT_P(1);
 4509 tgl                       456 GIC        3095 :     StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
                                457                 : 
                                458                 :     /* Oid      subtype = PG_GETARG_OID(3); */
 2580 teodor                    459 CBC        3095 :     bool       *recheck = (bool *) PG_GETARG_POINTER(4);
  878 akorotkov                 460 GIC        3095 :     int         siglen = GET_SIGLEN();
 4509 tgl                       461 CBC        3095 :     TRGM       *key = (TRGM *) DatumGetPointer(entry->key);
 4509 tgl                       462 ECB             :     TRGM       *qtrg;
                                463                 :     float8      res;
 4209 tgl                       464 GIC        3095 :     Size        querysize = VARSIZE(query);
 4509                           465            3095 :     char       *cache = (char *) fcinfo->flinfo->fn_extra;
 4509 tgl                       466 ECB             : 
 4209                           467                 :     /*
 3955 bruce                     468                 :      * Cache the generated trigrams across multiple calls with the same query.
                                469                 :      */
 4209 tgl                       470 GIC        3095 :     if (cache == NULL ||
 4209 tgl                       471 CBC        3091 :         VARSIZE(cache) != querysize ||
                                472            3091 :         memcmp(cache, query, querysize) != 0)
                                473                 :     {
                                474                 :         char       *newcache;
                                475                 : 
 4209 tgl                       476 GIC           4 :         qtrg = generate_trgm(VARDATA(query), querysize - VARHDRSZ);
 4209 tgl                       477 ECB             : 
 4209 tgl                       478 CBC           4 :         newcache = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
                                479               4 :                                       MAXALIGN(querysize) +
 4209 tgl                       480 GIC           4 :                                       VARSIZE(qtrg));
                                481                 : 
                                482               4 :         memcpy(newcache, query, querysize);
 4209 tgl                       483 CBC           4 :         memcpy(newcache + MAXALIGN(querysize), qtrg, VARSIZE(qtrg));
                                484                 : 
                                485               4 :         if (cache)
 4209 tgl                       486 LBC           0 :             pfree(cache);
 4209 tgl                       487 CBC           4 :         fcinfo->flinfo->fn_extra = newcache;
 4209 tgl                       488 GIC           4 :         cache = newcache;
 6797 bruce                     489 ECB             :     }
 6887 teodor                    490                 : 
 4209 tgl                       491 GIC        3095 :     qtrg = (TRGM *) (cache + MAXALIGN(querysize));
 4509 tgl                       492 ECB             : 
 4509 tgl                       493 GBC        3095 :     switch (strategy)
 4509 tgl                       494 ECB             :     {
 4509 tgl                       495 CBC        3095 :         case DistanceStrategyNumber:
                                496                 :         case WordDistanceStrategyNumber:
                                497                 :         case StrictWordDistanceStrategyNumber:
 1845 teodor                    498 ECB             :             /* Only plain trigram distance is exact */
 1845 teodor                    499 GIC        3095 :             *recheck = (strategy != DistanceStrategyNumber);
 4509 tgl                       500 CBC        3095 :             if (GIST_LEAF(entry))
                                501                 :             {                   /* all leafs contains orig trgm */
 2495 rhaas                     502 ECB             : 
                                503                 :                 /*
                                504                 :                  * Prevent gcc optimizing the sml variable using volatile
                                505                 :                  * keyword. Otherwise res can differ from the
 2580 teodor                    506                 :                  * word_similarity_dist_op() function.
                                507                 :                  */
 2580 teodor                    508 GIC        3057 :                 float4 volatile sml = cnt_sml(qtrg, key, *recheck);
                                509                 : 
                                510            3057 :                 res = 1.0 - sml;
                                511                 :             }
 4509 tgl                       512              38 :             else if (ISALLTRUE(key))
                                513                 :             {                   /* all leafs contains orig trgm */
 4509 tgl                       514 UIC           0 :                 res = 0.0;
 4509 tgl                       515 ECB             :             }
                                516                 :             else
 4382 bruce                     517                 :             {                   /* non-leaf contains signature */
 1105 akorotkov                 518 GIC          38 :                 int32       count = cnt_sml_sign_common(qtrg, GETSIGN(key), siglen);
 3940 peter_e                   519 CBC          38 :                 int32       len = ARRNELEM(qtrg);
                                520                 : 
 4509 tgl                       521 GBC          38 :                 res = (len == 0) ? -1.0 : 1.0 - ((float8) count) / ((float8) len);
                                522                 :             }
 4509 tgl                       523 GIC        3095 :             break;
 4509 tgl                       524 UIC           0 :         default:
 4509 tgl                       525 LBC           0 :             elog(ERROR, "unrecognized strategy number: %d", strategy);
 4509 tgl                       526 ECB             :             res = 0;            /* keep compiler quiet */
                                527                 :             break;
 6887 teodor                    528                 :     }
                                529                 : 
 4509 tgl                       530 CBC        3095 :     PG_RETURN_FLOAT8(res);
 6887 teodor                    531 EUB             : }
                                532                 : 
                                533                 : static int32
 1105 akorotkov                 534 GIC       52178 : unionkey(BITVECP sbase, TRGM *add, int siglen)
                                535                 : {
                                536                 :     int32       i;
 6887 teodor                    537 ECB             : 
 6887 teodor                    538 GIC       52178 :     if (ISSIGNKEY(add))
                                539                 :     {
                                540           26089 :         BITVECP     sadd = GETSIGN(add);
 6887 teodor                    541 ECB             : 
 6887 teodor                    542 GIC       26089 :         if (ISALLTRUE(add))
 6887 teodor                    543 UIC           0 :             return 1;
                                544                 : 
 1105 akorotkov                 545 CBC     3411481 :         LOOPBYTE(siglen)
 5623 bruce                     546 GIC     3385392 :             sbase[i] |= sadd[i];
 6887 teodor                    547 ECB             :     }
                                548                 :     else
                                549                 :     {
 6887 teodor                    550 GBC       26089 :         trgm       *ptr = GETARR(add);
 3940 peter_e                   551 GIC       26089 :         int32       tmp = 0;
 6887 teodor                    552 ECB             : 
 6797 bruce                     553 CBC      256318 :         for (i = 0; i < ARRNELEM(add); i++)
                                554                 :         {
 6797 bruce                     555 GIC      230229 :             CPTRGM(((char *) &tmp), ptr + i);
 1105 akorotkov                 556          230229 :             HASH(sbase, tmp, siglen);
 6887 teodor                    557 ECB             :         }
                                558                 :     }
 6887 teodor                    559 GIC       52178 :     return 0;
 6887 teodor                    560 ECB             : }
                                561                 : 
                                562                 : 
                                563                 : Datum
 6887 teodor                    564 GIC       26089 : gtrgm_union(PG_FUNCTION_ARGS)
                                565                 : {
 6797 bruce                     566 CBC       26089 :     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
 3940 peter_e                   567 GIC       26089 :     int32       len = entryvec->n;
 6887 teodor                    568           26089 :     int        *size = (int *) PG_GETARG_POINTER(1);
  878 akorotkov                 569           26089 :     int         siglen = GET_SIGLEN();
                                570                 :     int32       i;
 1105 akorotkov                 571 CBC       26089 :     TRGM       *result = gtrgm_alloc(false, siglen, NULL);
 1105 akorotkov                 572 GIC       26089 :     BITVECP     base = GETSIGN(result);
 6887 teodor                    573 ECB             : 
 6887 teodor                    574 CBC       78267 :     for (i = 0; i < len; i++)
 6887 teodor                    575 ECB             :     {
 1105 akorotkov                 576 CBC       52178 :         if (unionkey(base, GETENTRY(entryvec, i), siglen))
                                577                 :         {
 1105 akorotkov                 578 LBC           0 :             result->flag = ALLISTRUE;
                                579               0 :             SET_VARSIZE(result, CALCGTSIZE(ALLISTRUE, siglen));
 6887 teodor                    580 UIC           0 :             break;
 6887 teodor                    581 ECB             :         }
                                582                 :     }
                                583                 : 
 1105 akorotkov                 584 GIC       26089 :     *size = VARSIZE(result);
 6887 teodor                    585 EUB             : 
 6887 teodor                    586 GBC       26089 :     PG_RETURN_POINTER(result);
 6887 teodor                    587 EUB             : }
                                588                 : 
                                589                 : Datum
 6887 teodor                    590 GIC       26089 : gtrgm_same(PG_FUNCTION_ARGS)
 6887 teodor                    591 ECB             : {
 6797 bruce                     592 GIC       26089 :     TRGM       *a = (TRGM *) PG_GETARG_POINTER(0);
 6797 bruce                     593 CBC       26089 :     TRGM       *b = (TRGM *) PG_GETARG_POINTER(1);
 6887 teodor                    594 GIC       26089 :     bool       *result = (bool *) PG_GETARG_POINTER(2);
  878 akorotkov                 595           26089 :     int         siglen = GET_SIGLEN();
                                596                 : 
 6887 teodor                    597 CBC       26089 :     if (ISSIGNKEY(a))
                                598                 :     {                           /* then b also ISSIGNKEY */
                                599           26089 :         if (ISALLTRUE(a) && ISALLTRUE(b))
 6887 teodor                    600 LBC           0 :             *result = true;
 6887 teodor                    601 CBC       26089 :         else if (ISALLTRUE(a))
 6887 teodor                    602 LBC           0 :             *result = false;
 6887 teodor                    603 GIC       26089 :         else if (ISALLTRUE(b))
 6887 teodor                    604 LBC           0 :             *result = false;
                                605                 :         else
 6887 teodor                    606 ECB             :         {
 3940 peter_e                   607 EUB             :             int32       i;
 6887 teodor                    608 CBC       26089 :             BITVECP     sa = GETSIGN(a),
 6887 teodor                    609 GBC       26089 :                         sb = GETSIGN(b);
 6887 teodor                    610 ECB             : 
 6887 teodor                    611 GBC       26089 :             *result = true;
 1105 akorotkov                 612 GIC     1736581 :             LOOPBYTE(siglen)
                                613                 :             {
 5623 bruce                     614         1712087 :                 if (sa[i] != sb[i])
 5623 bruce                     615 ECB             :                 {
 5623 bruce                     616 CBC        1595 :                     *result = false;
 5623 bruce                     617 GIC        1595 :                     break;
 5623 bruce                     618 ECB             :                 }
 6887 teodor                    619                 :             }
                                620                 :         }
                                621                 :     }
                                622                 :     else
                                623                 :     {                           /* a and b ISARRKEY */
 3940 peter_e                   624 LBC           0 :         int32       lena = ARRNELEM(a),
 6887 teodor                    625 UIC           0 :                     lenb = ARRNELEM(b);
                                626                 : 
                                627               0 :         if (lena != lenb)
                                628               0 :             *result = false;
                                629                 :         else
                                630                 :         {
 6887 teodor                    631 UBC           0 :             trgm       *ptra = GETARR(a),
                                632               0 :                        *ptrb = GETARR(b);
                                633                 :             int32       i;
 6887 teodor                    634 EUB             : 
 6887 teodor                    635 UBC           0 :             *result = true;
 6887 teodor                    636 UIC           0 :             for (i = 0; i < lena; i++)
 6797 bruce                     637               0 :                 if (CMPTRGM(ptra + i, ptrb + i))
 6887 teodor                    638 EUB             :                 {
 6887 teodor                    639 UBC           0 :                     *result = false;
 6887 teodor                    640 UIC           0 :                     break;
                                641                 :                 }
 6887 teodor                    642 EUB             :         }
                                643                 :     }
                                644                 : 
 6887 teodor                    645 GIC       26089 :     PG_RETURN_POINTER(result);
 6887 teodor                    646 EUB             : }
                                647                 : 
                                648                 : static int32
 1105 akorotkov                 649 UIC           0 : sizebitvec(BITVECP sign, int siglen)
                                650                 : {
                                651               0 :     return pg_popcount(sign, siglen);
 6887 teodor                    652 ECB             : }
                                653                 : 
                                654                 : static int
 1105 akorotkov                 655 GIC     4881920 : hemdistsign(BITVECP a, BITVECP b, int siglen)
 6797 bruce                     656 EUB             : {
                                657                 :     int         i,
 6288 tgl                       658                 :                 diff,
 6797 bruce                     659 GIC     4881920 :                 dist = 0;
                                660                 : 
 1105 akorotkov                 661       200037508 :     LOOPBYTE(siglen)
 5623 bruce                     662 ECB             :     {
 5623 bruce                     663 GIC   195155588 :         diff = (unsigned char) (a[i] ^ b[i]);
                                664                 :         /* Using the popcount functions here isn't likely to win */
 1514 tgl                       665       195155588 :         dist += pg_number_of_ones[diff];
 5623 bruce                     666 ECB             :     }
 6887 teodor                    667 GIC     4881920 :     return dist;
 6887 teodor                    668 ECB             : }
                                669                 : 
                                670                 : static int
 1105 akorotkov                 671 UIC           0 : hemdist(TRGM *a, TRGM *b, int siglen)
 6797 bruce                     672 ECB             : {
 6797 bruce                     673 UIC           0 :     if (ISALLTRUE(a))
 6797 bruce                     674 ECB             :     {
 6887 teodor                    675 UIC           0 :         if (ISALLTRUE(b))
                                676               0 :             return 0;
                                677                 :         else
 1105 akorotkov                 678 UBC           0 :             return SIGLENBIT(siglen) - sizebitvec(GETSIGN(b), siglen);
                                679                 :     }
 6797 bruce                     680               0 :     else if (ISALLTRUE(b))
 1105 akorotkov                 681 UIC           0 :         return SIGLENBIT(siglen) - sizebitvec(GETSIGN(a), siglen);
 6887 teodor                    682 EUB             : 
 1105 akorotkov                 683 UBC           0 :     return hemdistsign(GETSIGN(a), GETSIGN(b), siglen);
                                684                 : }
 6887 teodor                    685 EUB             : 
                                686                 : Datum
 6887 teodor                    687 GBC     1211606 : gtrgm_penalty(PG_FUNCTION_ARGS)
 6887 teodor                    688 EUB             : {
 6887 teodor                    689 GIC     1211606 :     GISTENTRY  *origentry = (GISTENTRY *) PG_GETARG_POINTER(0); /* always ISSIGNKEY */
 6887 teodor                    690 GBC     1211606 :     GISTENTRY  *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
 6887 teodor                    691 GIC     1211606 :     float      *penalty = (float *) PG_GETARG_POINTER(2);
  878 akorotkov                 692         1211606 :     int         siglen = GET_SIGLEN();
 6797 bruce                     693         1211606 :     TRGM       *origval = (TRGM *) DatumGetPointer(origentry->key);
 6797 bruce                     694 CBC     1211606 :     TRGM       *newval = (TRGM *) DatumGetPointer(newentry->key);
 6887 teodor                    695 GIC     1211606 :     BITVECP     orig = GETSIGN(origval);
 6887 teodor                    696 ECB             : 
 6887 teodor                    697 CBC     1211606 :     *penalty = 0.0;
 6887 teodor                    698 ECB             : 
 6797 bruce                     699 CBC     1211606 :     if (ISARRKEY(newval))
 6797 bruce                     700 ECB             :     {
 4209 tgl                       701 CBC     1211606 :         char       *cache = (char *) fcinfo->flinfo->fn_extra;
 1105 akorotkov                 702         1211606 :         TRGM       *cachedVal = (TRGM *) (cache + MAXALIGN(siglen));
 4209 tgl                       703 GIC     1211606 :         Size        newvalsize = VARSIZE(newval);
 4209 tgl                       704 ECB             :         BITVECP     sign;
                                705                 : 
                                706                 :         /*
                                707                 :          * Cache the sign data across multiple calls with the same newval.
                                708                 :          */
 4209 tgl                       709 CBC     1211606 :         if (cache == NULL ||
                                710         1211601 :             VARSIZE(cachedVal) != newvalsize ||
 4209 tgl                       711 GIC     1210574 :             memcmp(cachedVal, newval, newvalsize) != 0)
                                712                 :         {
                                713                 :             char       *newcache;
                                714                 : 
                                715            2886 :             newcache = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
 1105 akorotkov                 716 CBC        2886 :                                           MAXALIGN(siglen) +
 4209 tgl                       717 ECB             :                                           newvalsize);
                                718                 : 
 1105 akorotkov                 719 GIC        2886 :             makesign((BITVECP) newcache, newval, siglen);
                                720                 : 
                                721            2886 :             cachedVal = (TRGM *) (newcache + MAXALIGN(siglen));
 4209 tgl                       722 CBC        2886 :             memcpy(cachedVal, newval, newvalsize);
 4209 tgl                       723 ECB             : 
 4209 tgl                       724 GIC        2886 :             if (cache)
                                725            2881 :                 pfree(cache);
 4209 tgl                       726 CBC        2886 :             fcinfo->flinfo->fn_extra = newcache;
 4209 tgl                       727 GIC        2886 :             cache = newcache;
 4209 tgl                       728 ECB             :         }
                                729                 : 
 4209 tgl                       730 GIC     1211606 :         sign = (BITVECP) cache;
 6887 teodor                    731 ECB             : 
 6797 bruce                     732 CBC     1211606 :         if (ISALLTRUE(origval))
 1105 akorotkov                 733 LBC           0 :             *penalty = ((float) (SIGLENBIT(siglen) - sizebitvec(sign, siglen))) / (float) (SIGLENBIT(siglen) + 1);
 6797 bruce                     734 ECB             :         else
 1105 akorotkov                 735 GIC     1211606 :             *penalty = hemdistsign(sign, orig, siglen);
                                736                 :     }
 6797 bruce                     737 ECB             :     else
 1105 akorotkov                 738 UIC           0 :         *penalty = hemdist(origval, newval, siglen);
 6887 teodor                    739 CBC     1211606 :     PG_RETURN_POINTER(penalty);
 6887 teodor                    740 EUB             : }
                                741                 : 
 6887 teodor                    742 ECB             : typedef struct
                                743                 : {
                                744                 :     bool        allistrue;
 1105 akorotkov                 745 EUB             :     BITVECP     sign;
 5623 bruce                     746 ECB             : } CACHESIGN;
                                747                 : 
                                748                 : static void
 1105 akorotkov                 749 GIC       43116 : fillcache(CACHESIGN *item, TRGM *key, BITVECP sign, int siglen)
                                750                 : {
 6887 teodor                    751           43116 :     item->allistrue = false;
 1105 akorotkov                 752           43116 :     item->sign = sign;
 6887 teodor                    753           43116 :     if (ISARRKEY(key))
 1105 akorotkov                 754           42904 :         makesign(item->sign, key, siglen);
 6887 teodor                    755             212 :     else if (ISALLTRUE(key))
 6887 teodor                    756 LBC           0 :         item->allistrue = true;
                                757                 :     else
   61 peter                     758 GNC         212 :         memcpy(item->sign, GETSIGN(key), siglen);
 6887 teodor                    759 CBC       43116 : }
 6887 teodor                    760 ECB             : 
                                761                 : #define WISH_F(a,b,c) (double)( -(double)(((a)-(b))*((a)-(b))*((a)-(b)))*(c) )
                                762                 : typedef struct
 6887 teodor                    763 EUB             : {
                                764                 :     OffsetNumber pos;
 3940 peter_e                   765 ECB             :     int32       cost;
 5623 bruce                     766                 : } SPLITCOST;
                                767                 : 
                                768                 : static int
 6887 teodor                    769 GIC       47803 : comparecost(const void *a, const void *b)
                                770                 : {
 4228 peter_e                   771           47803 :     if (((const SPLITCOST *) a)->cost == ((const SPLITCOST *) b)->cost)
 6887 teodor                    772           43155 :         return 0;
                                773                 :     else
 4228 peter_e                   774            4648 :         return (((const SPLITCOST *) a)->cost > ((const SPLITCOST *) b)->cost) ? 1 : -1;
                                775                 : }
 6887 teodor                    776 ECB             : 
                                777                 : 
                                778                 : static int
 1105 akorotkov                 779 CBC     3585154 : hemdistcache(CACHESIGN *a, CACHESIGN *b, int siglen)
                                780                 : {
 6797 bruce                     781         3585154 :     if (a->allistrue)
                                782                 :     {
 6887 teodor                    783 UIC           0 :         if (b->allistrue)
                                784               0 :             return 0;
                                785                 :         else
 1105 akorotkov                 786 LBC           0 :             return SIGLENBIT(siglen) - sizebitvec(b->sign, siglen);
                                787                 :     }
 6797 bruce                     788 CBC     3585154 :     else if (b->allistrue)
 1105 akorotkov                 789 UIC           0 :         return SIGLENBIT(siglen) - sizebitvec(a->sign, siglen);
 6887 teodor                    790 EUB             : 
 1105 akorotkov                 791 GBC     3585154 :     return hemdistsign(a->sign, b->sign, siglen);
                                792                 : }
 6887 teodor                    793 EUB             : 
                                794                 : Datum
 6887 teodor                    795 CBC         268 : gtrgm_picksplit(PG_FUNCTION_ARGS)
 6887 teodor                    796 EUB             : {
 6797 bruce                     797 GIC         268 :     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
  878 rhodiumtoad               798 CBC         268 :     OffsetNumber maxoff = entryvec->n - 1;
 6887 teodor                    799 GIC         268 :     GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
  878 akorotkov                 800             268 :     int         siglen = GET_SIGLEN();
                                801                 :     OffsetNumber k,
 6887 teodor                    802 ECB             :                 j;
                                803                 :     TRGM       *datum_l,
                                804                 :                *datum_r;
                                805                 :     BITVECP     union_l,
                                806                 :                 union_r;
 3940 peter_e                   807                 :     int32       size_alpha,
                                808                 :                 size_beta;
                                809                 :     int32       size_waste,
 6887 teodor                    810 GIC         268 :                 waste = -1;
                                811                 :     int32       nbytes;
                                812             268 :     OffsetNumber seed_1 = 0,
                                813             268 :                 seed_2 = 0;
                                814                 :     OffsetNumber *left,
                                815                 :                *right;
                                816                 :     BITVECP     ptr;
 6887 teodor                    817 ECB             :     int         i;
                                818                 :     CACHESIGN  *cache;
 1105 akorotkov                 819                 :     char       *cache_sign;
 6887 teodor                    820                 :     SPLITCOST  *costvector;
                                821                 : 
                                822                 :     /* cache the sign data for each existing item */
  878 rhodiumtoad               823 GIC         268 :     cache = (CACHESIGN *) palloc(sizeof(CACHESIGN) * (maxoff + 1));
                                824             268 :     cache_sign = palloc(siglen * (maxoff + 1));
                                825                 : 
 4209 tgl                       826           43384 :     for (k = FirstOffsetNumber; k <= maxoff; k = OffsetNumberNext(k))
 1105 akorotkov                 827           43116 :         fillcache(&cache[k], GETENTRY(entryvec, k), &cache_sign[siglen * k],
                                828                 :                   siglen);
                                829                 : 
 4209 tgl                       830 ECB             :     /* now find the two furthest-apart items */
 6797 bruce                     831 CBC       43116 :     for (k = FirstOffsetNumber; k < maxoff; k = OffsetNumberNext(k))
                                832                 :     {
                                833         3541770 :         for (j = OffsetNumberNext(k); j <= maxoff; j = OffsetNumberNext(j))
 6797 bruce                     834 ECB             :         {
 1105 akorotkov                 835 GIC     3498922 :             size_waste = hemdistcache(&(cache[j]), &(cache[k]), siglen);
 6797 bruce                     836         3498922 :             if (size_waste > waste)
                                837                 :             {
 6887 teodor                    838 CBC         463 :                 waste = size_waste;
 6887 teodor                    839 GIC         463 :                 seed_1 = k;
 6887 teodor                    840 CBC         463 :                 seed_2 = j;
                                841                 :             }
 6887 teodor                    842 ECB             :         }
                                843                 :     }
                                844                 : 
 4209 tgl                       845                 :     /* just in case we didn't make a selection ... */
 6797 bruce                     846 CBC         268 :     if (seed_1 == 0 || seed_2 == 0)
 6797 bruce                     847 ECB             :     {
 6887 teodor                    848 UIC           0 :         seed_1 = 1;
                                849               0 :         seed_2 = 2;
                                850                 :     }
                                851                 : 
                                852                 :     /* initialize the result vectors */
  878 rhodiumtoad               853 CBC         268 :     nbytes = maxoff * sizeof(OffsetNumber);
 4209 tgl                       854 GIC         268 :     v->spl_left = left = (OffsetNumber *) palloc(nbytes);
 4209 tgl                       855 GBC         268 :     v->spl_right = right = (OffsetNumber *) palloc(nbytes);
                                856             268 :     v->spl_nleft = 0;
 4209 tgl                       857 GIC         268 :     v->spl_nright = 0;
                                858                 : 
                                859                 :     /* form initial .. */
 1105 akorotkov                 860 CBC         268 :     datum_l = gtrgm_alloc(cache[seed_1].allistrue, siglen, cache[seed_1].sign);
                                861             268 :     datum_r = gtrgm_alloc(cache[seed_2].allistrue, siglen, cache[seed_2].sign);
 6887 teodor                    862 ECB             : 
 6797 bruce                     863 CBC         268 :     union_l = GETSIGN(datum_l);
                                864             268 :     union_r = GETSIGN(datum_r);
                                865                 : 
                                866                 :     /* sort before ... */
 6887 teodor                    867             268 :     costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
 6797 bruce                     868           43384 :     for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
                                869                 :     {
 6887 teodor                    870           43116 :         costvector[j - 1].pos = j;
 1105 akorotkov                 871           43116 :         size_alpha = hemdistcache(&(cache[seed_1]), &(cache[j]), siglen);
 1105 akorotkov                 872 GIC       43116 :         size_beta = hemdistcache(&(cache[seed_2]), &(cache[j]), siglen);
 6887 teodor                    873           43116 :         costvector[j - 1].cost = abs(size_alpha - size_beta);
 6887 teodor                    874 ECB             :     }
   61 peter                     875 GNC         268 :     qsort(costvector, maxoff, sizeof(SPLITCOST), comparecost);
                                876                 : 
 6797 bruce                     877 CBC       43384 :     for (k = 0; k < maxoff; k++)
 6797 bruce                     878 ECB             :     {
 6887 teodor                    879 CBC       43116 :         j = costvector[k].pos;
 6797 bruce                     880           43116 :         if (j == seed_1)
                                881                 :         {
 6887 teodor                    882             268 :             *left++ = j;
 6887 teodor                    883 GIC         268 :             v->spl_nleft++;
 6887 teodor                    884 CBC         268 :             continue;
                                885                 :         }
 6797 bruce                     886           42848 :         else if (j == seed_2)
 6797 bruce                     887 ECB             :         {
 6887 teodor                    888 GIC         268 :             *right++ = j;
 6887 teodor                    889 CBC         268 :             v->spl_nright++;
                                890             268 :             continue;
 6887 teodor                    891 ECB             :         }
                                892                 : 
 6797 bruce                     893 CBC       42580 :         if (ISALLTRUE(datum_l) || cache[j].allistrue)
                                894                 :         {
 6797 bruce                     895 LBC           0 :             if (ISALLTRUE(datum_l) && cache[j].allistrue)
                                896               0 :                 size_alpha = 0;
 6887 teodor                    897 ECB             :             else
 1105 akorotkov                 898 UIC           0 :                 size_alpha = SIGLENBIT(siglen) -
 1165 alvherre                  899               0 :                     sizebitvec((cache[j].allistrue) ? GETSIGN(datum_l) :
 1105 akorotkov                 900 LBC           0 :                                GETSIGN(cache[j].sign),
                                901                 :                                siglen);
 6887 teodor                    902 EUB             :         }
 6797 bruce                     903                 :         else
 1105 akorotkov                 904 GIC       42580 :             size_alpha = hemdistsign(cache[j].sign, GETSIGN(datum_l), siglen);
 6887 teodor                    905 EUB             : 
 6797 bruce                     906 GBC       42580 :         if (ISALLTRUE(datum_r) || cache[j].allistrue)
 6797 bruce                     907 EUB             :         {
 6797 bruce                     908 UIC           0 :             if (ISALLTRUE(datum_r) && cache[j].allistrue)
                                909               0 :                 size_beta = 0;
                                910                 :             else
 1105 akorotkov                 911 LBC           0 :                 size_beta = SIGLENBIT(siglen) -
 1165 alvherre                  912 UIC           0 :                     sizebitvec((cache[j].allistrue) ? GETSIGN(datum_r) :
 1105 akorotkov                 913 LBC           0 :                                GETSIGN(cache[j].sign),
                                914                 :                                siglen);
 6887 teodor                    915 EUB             :         }
 6797 bruce                     916                 :         else
 1105 akorotkov                 917 GIC       42580 :             size_beta = hemdistsign(cache[j].sign, GETSIGN(datum_r), siglen);
 6887 teodor                    918 EUB             : 
 6797 bruce                     919 GBC       42580 :         if (size_alpha < size_beta + WISH_F(v->spl_nleft, v->spl_nright, 0.1))
 6797 bruce                     920 EUB             :         {
 6797 bruce                     921 GIC       21175 :             if (ISALLTRUE(datum_l) || cache[j].allistrue)
                                922                 :             {
 6797 bruce                     923 UIC           0 :                 if (!ISALLTRUE(datum_l))
   61 peter                     924 UNC           0 :                     memset(GETSIGN(datum_l), 0xff, siglen);
                                925                 :             }
 6797 bruce                     926 ECB             :             else
                                927                 :             {
 6797 bruce                     928 CBC       21175 :                 ptr = cache[j].sign;
 1105 akorotkov                 929 GIC     1271215 :                 LOOPBYTE(siglen)
 5623 bruce                     930 GBC     1250040 :                     union_l[i] |= ptr[i];
 6887 teodor                    931 EUB             :             }
 6887 teodor                    932 GIC       21175 :             *left++ = j;
                                933           21175 :             v->spl_nleft++;
                                934                 :         }
 6797 bruce                     935 ECB             :         else
                                936                 :         {
 6797 bruce                     937 CBC       21405 :             if (ISALLTRUE(datum_r) || cache[j].allistrue)
                                938                 :             {
 6797 bruce                     939 LBC           0 :                 if (!ISALLTRUE(datum_r))
   61 peter                     940 UNC           0 :                     memset(GETSIGN(datum_r), 0xff, siglen);
                                941                 :             }
                                942                 :             else
                                943                 :             {
 6797 bruce                     944 CBC       21405 :                 ptr = cache[j].sign;
 1105 akorotkov                 945 GIC     1237989 :                 LOOPBYTE(siglen)
 5623 bruce                     946 GBC     1216584 :                     union_r[i] |= ptr[i];
 6887 teodor                    947 EUB             :             }
 6887 teodor                    948 GIC       21405 :             *right++ = j;
                                949           21405 :             v->spl_nright++;
                                950                 :         }
 6887 teodor                    951 ECB             :     }
                                952                 : 
 6887 teodor                    953 CBC         268 :     v->spl_ldatum = PointerGetDatum(datum_l);
 6887 teodor                    954 GIC         268 :     v->spl_rdatum = PointerGetDatum(datum_r);
 6887 teodor                    955 ECB             : 
 6887 teodor                    956 CBC         268 :     PG_RETURN_POINTER(v);
                                957                 : }
                                958                 : 
                                959                 : Datum
 1105 akorotkov                 960              17 : gtrgm_options(PG_FUNCTION_ARGS)
 1105 akorotkov                 961 ECB             : {
 1105 akorotkov                 962 GIC          17 :     local_relopts *relopts = (local_relopts *) PG_GETARG_POINTER(0);
 1105 akorotkov                 963 ECB             : 
 1105 akorotkov                 964 GIC          17 :     init_local_reloptions(relopts, sizeof(TrgmGistOptions));
                                965              17 :     add_local_int_reloption(relopts, "siglen",
                                966                 :                             "signature length in bytes",
 1105 akorotkov                 967 ECB             :                             SIGLEN_DEFAULT, 1, SIGLEN_MAX,
                                968                 :                             offsetof(TrgmGistOptions, siglen));
                                969                 : 
 1105 akorotkov                 970 GIC          17 :     PG_RETURN_VOID();
 1105 akorotkov                 971 ECB             : }
        

Generated by: LCOV version v1.16-55-g56c0a2a