LCOV - code coverage report
Current view: top level - src/backend/utils/adt - tsquery_gist.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 8 117 6.8 %
Date: 2017-09-29 13:40:31 Functions: 1 11 9.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * tsquery_gist.c
       4             :  *    GiST index support for tsquery
       5             :  *
       6             :  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
       7             :  *
       8             :  *
       9             :  * IDENTIFICATION
      10             :  *    src/backend/utils/adt/tsquery_gist.c
      11             :  *
      12             :  *-------------------------------------------------------------------------
      13             :  */
      14             : 
      15             : #include "postgres.h"
      16             : 
      17             : #include "access/stratnum.h"
      18             : #include "access/gist.h"
      19             : #include "tsearch/ts_utils.h"
      20             : #include "utils/builtins.h"
      21             : 
      22             : #define GETENTRY(vec,pos) DatumGetTSQuerySign((vec)->vector[pos].key)
      23             : 
      24             : 
      25             : Datum
      26           6 : gtsquery_compress(PG_FUNCTION_ARGS)
      27             : {
      28           6 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
      29           6 :     GISTENTRY  *retval = entry;
      30             : 
      31           6 :     if (entry->leafkey)
      32             :     {
      33             :         TSQuerySign sign;
      34             : 
      35           6 :         retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
      36           6 :         sign = makeTSQuerySign(DatumGetTSQuery(entry->key));
      37             : 
      38           6 :         gistentryinit(*retval, TSQuerySignGetDatum(sign),
      39             :                       entry->rel, entry->page,
      40             :                       entry->offset, FALSE);
      41             :     }
      42             : 
      43           6 :     PG_RETURN_POINTER(retval);
      44             : }
      45             : 
      46             : Datum
      47           0 : gtsquery_decompress(PG_FUNCTION_ARGS)
      48             : {
      49           0 :     PG_RETURN_DATUM(PG_GETARG_DATUM(0));
      50             : }
      51             : 
      52             : Datum
      53           0 : gtsquery_consistent(PG_FUNCTION_ARGS)
      54             : {
      55           0 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
      56           0 :     TSQuery     query = PG_GETARG_TSQUERY(1);
      57           0 :     StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
      58             : 
      59             :     /* Oid      subtype = PG_GETARG_OID(3); */
      60           0 :     bool       *recheck = (bool *) PG_GETARG_POINTER(4);
      61           0 :     TSQuerySign key = DatumGetTSQuerySign(entry->key);
      62           0 :     TSQuerySign sq = makeTSQuerySign(query);
      63             :     bool        retval;
      64             : 
      65             :     /* All cases served by this function are inexact */
      66           0 :     *recheck = true;
      67             : 
      68           0 :     switch (strategy)
      69             :     {
      70             :         case RTContainsStrategyNumber:
      71           0 :             if (GIST_LEAF(entry))
      72           0 :                 retval = (key & sq) == sq;
      73             :             else
      74           0 :                 retval = (key & sq) != 0;
      75           0 :             break;
      76             :         case RTContainedByStrategyNumber:
      77           0 :             if (GIST_LEAF(entry))
      78           0 :                 retval = (key & sq) == key;
      79             :             else
      80           0 :                 retval = (key & sq) != 0;
      81           0 :             break;
      82             :         default:
      83           0 :             retval = FALSE;
      84             :     }
      85           0 :     PG_RETURN_BOOL(retval);
      86             : }
      87             : 
      88             : Datum
      89           0 : gtsquery_union(PG_FUNCTION_ARGS)
      90             : {
      91           0 :     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
      92           0 :     int        *size = (int *) PG_GETARG_POINTER(1);
      93             :     TSQuerySign sign;
      94             :     int         i;
      95             : 
      96           0 :     sign = 0;
      97             : 
      98           0 :     for (i = 0; i < entryvec->n; i++)
      99           0 :         sign |= GETENTRY(entryvec, i);
     100             : 
     101           0 :     *size = sizeof(TSQuerySign);
     102             : 
     103           0 :     PG_RETURN_TSQUERYSIGN(sign);
     104             : }
     105             : 
     106             : Datum
     107           0 : gtsquery_same(PG_FUNCTION_ARGS)
     108             : {
     109           0 :     TSQuerySign a = PG_GETARG_TSQUERYSIGN(0);
     110           0 :     TSQuerySign b = PG_GETARG_TSQUERYSIGN(1);
     111           0 :     bool       *result = (bool *) PG_GETARG_POINTER(2);
     112             : 
     113           0 :     *result = (a == b) ? true : false;
     114             : 
     115           0 :     PG_RETURN_POINTER(result);
     116             : }
     117             : 
     118             : static int
     119           0 : sizebitvec(TSQuerySign sign)
     120             : {
     121           0 :     int         size = 0,
     122             :                 i;
     123             : 
     124           0 :     for (i = 0; i < TSQS_SIGLEN; i++)
     125           0 :         size += 0x01 & (sign >> i);
     126             : 
     127           0 :     return size;
     128             : }
     129             : 
     130             : static int
     131           0 : hemdist(TSQuerySign a, TSQuerySign b)
     132             : {
     133           0 :     TSQuerySign res = a ^ b;
     134             : 
     135           0 :     return sizebitvec(res);
     136             : }
     137             : 
     138             : Datum
     139           0 : gtsquery_penalty(PG_FUNCTION_ARGS)
     140             : {
     141           0 :     TSQuerySign origval = DatumGetTSQuerySign(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
     142           0 :     TSQuerySign newval = DatumGetTSQuerySign(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
     143           0 :     float      *penalty = (float *) PG_GETARG_POINTER(2);
     144             : 
     145           0 :     *penalty = hemdist(origval, newval);
     146             : 
     147           0 :     PG_RETURN_POINTER(penalty);
     148             : }
     149             : 
     150             : 
     151             : typedef struct
     152             : {
     153             :     OffsetNumber pos;
     154             :     int32       cost;
     155             : } SPLITCOST;
     156             : 
     157             : static int
     158           0 : comparecost(const void *a, const void *b)
     159             : {
     160           0 :     if (((const SPLITCOST *) a)->cost == ((const SPLITCOST *) b)->cost)
     161           0 :         return 0;
     162             :     else
     163           0 :         return (((const SPLITCOST *) a)->cost > ((const SPLITCOST *) b)->cost) ? 1 : -1;
     164             : }
     165             : 
     166             : #define WISH_F(a,b,c) (double)( -(double)(((a)-(b))*((a)-(b))*((a)-(b)))*(c) )
     167             : 
     168             : Datum
     169           0 : gtsquery_picksplit(PG_FUNCTION_ARGS)
     170             : {
     171           0 :     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
     172           0 :     GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
     173           0 :     OffsetNumber maxoff = entryvec->n - 2;
     174             :     OffsetNumber k,
     175             :                 j;
     176             :     TSQuerySign datum_l,
     177             :                 datum_r;
     178             :     int32       size_alpha,
     179             :                 size_beta;
     180             :     int32       size_waste,
     181           0 :                 waste = -1;
     182             :     int32       nbytes;
     183           0 :     OffsetNumber seed_1 = 0,
     184           0 :                 seed_2 = 0;
     185             :     OffsetNumber *left,
     186             :                *right;
     187             : 
     188             :     SPLITCOST  *costvector;
     189             : 
     190           0 :     nbytes = (maxoff + 2) * sizeof(OffsetNumber);
     191           0 :     left = v->spl_left = (OffsetNumber *) palloc(nbytes);
     192           0 :     right = v->spl_right = (OffsetNumber *) palloc(nbytes);
     193           0 :     v->spl_nleft = v->spl_nright = 0;
     194             : 
     195           0 :     for (k = FirstOffsetNumber; k < maxoff; k = OffsetNumberNext(k))
     196           0 :         for (j = OffsetNumberNext(k); j <= maxoff; j = OffsetNumberNext(j))
     197             :         {
     198           0 :             size_waste = hemdist(GETENTRY(entryvec, j), GETENTRY(entryvec, k));
     199           0 :             if (size_waste > waste)
     200             :             {
     201           0 :                 waste = size_waste;
     202           0 :                 seed_1 = k;
     203           0 :                 seed_2 = j;
     204             :             }
     205             :         }
     206             : 
     207             : 
     208           0 :     if (seed_1 == 0 || seed_2 == 0)
     209             :     {
     210           0 :         seed_1 = 1;
     211           0 :         seed_2 = 2;
     212             :     }
     213             : 
     214           0 :     datum_l = GETENTRY(entryvec, seed_1);
     215           0 :     datum_r = GETENTRY(entryvec, seed_2);
     216             : 
     217           0 :     maxoff = OffsetNumberNext(maxoff);
     218           0 :     costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
     219           0 :     for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
     220             :     {
     221           0 :         costvector[j - 1].pos = j;
     222           0 :         size_alpha = hemdist(GETENTRY(entryvec, seed_1), GETENTRY(entryvec, j));
     223           0 :         size_beta = hemdist(GETENTRY(entryvec, seed_2), GETENTRY(entryvec, j));
     224           0 :         costvector[j - 1].cost = abs(size_alpha - size_beta);
     225             :     }
     226           0 :     qsort((void *) costvector, maxoff, sizeof(SPLITCOST), comparecost);
     227             : 
     228           0 :     for (k = 0; k < maxoff; k++)
     229             :     {
     230           0 :         j = costvector[k].pos;
     231           0 :         if (j == seed_1)
     232             :         {
     233           0 :             *left++ = j;
     234           0 :             v->spl_nleft++;
     235           0 :             continue;
     236             :         }
     237           0 :         else if (j == seed_2)
     238             :         {
     239           0 :             *right++ = j;
     240           0 :             v->spl_nright++;
     241           0 :             continue;
     242             :         }
     243           0 :         size_alpha = hemdist(datum_l, GETENTRY(entryvec, j));
     244           0 :         size_beta = hemdist(datum_r, GETENTRY(entryvec, j));
     245             : 
     246           0 :         if (size_alpha < size_beta + WISH_F(v->spl_nleft, v->spl_nright, 0.05))
     247             :         {
     248           0 :             datum_l |= GETENTRY(entryvec, j);
     249           0 :             *left++ = j;
     250           0 :             v->spl_nleft++;
     251             :         }
     252             :         else
     253             :         {
     254           0 :             datum_r |= GETENTRY(entryvec, j);
     255           0 :             *right++ = j;
     256           0 :             v->spl_nright++;
     257             :         }
     258             :     }
     259             : 
     260           0 :     *right = *left = FirstOffsetNumber;
     261           0 :     v->spl_ldatum = TSQuerySignGetDatum(datum_l);
     262           0 :     v->spl_rdatum = TSQuerySignGetDatum(datum_r);
     263             : 
     264           0 :     PG_RETURN_POINTER(v);
     265             : }
     266             : 
     267             : /*
     268             :  * Formerly, gtsquery_consistent was declared in pg_proc.h with arguments
     269             :  * that did not match the documented conventions for GiST support functions.
     270             :  * We fixed that, but we still need a pg_proc entry with the old signature
     271             :  * to support reloading pre-9.6 contrib/tsearch2 opclass declarations.
     272             :  * This compatibility function should go away eventually.
     273             :  */
     274             : Datum
     275           0 : gtsquery_consistent_oldsig(PG_FUNCTION_ARGS)
     276             : {
     277           0 :     return gtsquery_consistent(fcinfo);
     278             : }

Generated by: LCOV version 1.11