LCOV - differential code coverage report
Current view: top level - src/test/modules/spgist_name_ops - spgist_name_ops.c (source / functions) Coverage Total Hit UNC LBC UBC GBC GNC CBC EUB ECB DUB DCB
Current: 0e5ff9b9b45a657aea12440478dc002e9b01f138 vs 0123ce131fca454009439dfa3b2266d1d40737d7 Lines: 83.3 % 234 195 1 4 34 5 190 1 1 1 5
Current Date: 2026-03-14 14:10:32 -0400 Functions: 100.0 % 14 14 5 9 1
Baseline: lcov-20260315-024220-baseline Branches: 69.2 % 104 72 2 30 1 71 82 16
Baseline Date: 2026-03-14 15:27:56 +0100 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(30,360] days: 83.3 % 6 5 1 5
(360..) days: 83.3 % 228 190 4 34 190 1 1
Function coverage date bins:
(30,360] days: 100.0 % 1 1 1
(360..) days: 100.0 % 13 13 4 9
Branch coverage date bins:
(360..) days: 35.6 % 202 72 2 30 1 71 82 16

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*--------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * spgist_name_ops.c
                                  4                 :                :  *      Test opclass for SP-GiST
                                  5                 :                :  *
                                  6                 :                :  * This indexes input values of type "name", but the index storage is "text",
                                  7                 :                :  * with the same choices as made in the core SP-GiST text_ops opclass.
                                  8                 :                :  * Much of the code is identical to src/backend/access/spgist/spgtextproc.c,
                                  9                 :                :  * which see for a more detailed header comment.
                                 10                 :                :  *
                                 11                 :                :  * Unlike spgtextproc.c, we don't bother with collation-aware logic.
                                 12                 :                :  *
                                 13                 :                :  *
                                 14                 :                :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
                                 15                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                 16                 :                :  *
                                 17                 :                :  * IDENTIFICATION
                                 18                 :                :  *      src/test/modules/spgist_name_ops/spgist_name_ops.c
                                 19                 :                :  *
                                 20                 :                :  * -------------------------------------------------------------------------
                                 21                 :                :  */
                                 22                 :                : #include "postgres.h"
                                 23                 :                : 
                                 24                 :                : #include "access/spgist.h"
                                 25                 :                : #include "catalog/pg_type.h"
                                 26                 :                : #include "utils/datum.h"
                                 27                 :                : #include "varatt.h"
                                 28                 :                : 
 1806 tgl@sss.pgh.pa.us          29                 :CBC           1 : PG_MODULE_MAGIC;
                                 30                 :                : 
                                 31                 :                : 
                                 32                 :              2 : PG_FUNCTION_INFO_V1(spgist_name_config);
                                 33                 :                : Datum
                                 34                 :              7 : spgist_name_config(PG_FUNCTION_ARGS)
                                 35                 :                : {
                                 36                 :                : #ifdef NOT_USED
                                 37                 :                :     spgConfigIn *cfgin = (spgConfigIn *) PG_GETARG_POINTER(0);
                                 38                 :                : #endif
                                 39                 :              7 :     spgConfigOut *cfg = (spgConfigOut *) PG_GETARG_POINTER(1);
                                 40                 :                : 
                                 41                 :              7 :     cfg->prefixType = TEXTOID;
                                 42                 :              7 :     cfg->labelType = INT2OID;
                                 43                 :              7 :     cfg->leafType = TEXTOID;
                                 44                 :              7 :     cfg->canReturnData = true;
                                 45                 :              7 :     cfg->longValuesOK = true;    /* suffixing will shorten long values */
                                 46                 :              7 :     PG_RETURN_VOID();
                                 47                 :                : }
                                 48                 :                : 
                                 49                 :                : /*
                                 50                 :                :  * Form a text datum from the given not-necessarily-null-terminated string,
                                 51                 :                :  * using short varlena header format if possible
                                 52                 :                :  */
                                 53                 :                : static Datum
                                 54                 :          18284 : formTextDatum(const char *data, int datalen)
                                 55                 :                : {
                                 56                 :                :     char       *p;
                                 57                 :                : 
                                 58                 :          18284 :     p = (char *) palloc(datalen + VARHDRSZ);
                                 59                 :                : 
                                 60         [ +  - ]:          18284 :     if (datalen + VARHDRSZ_SHORT <= VARATT_SHORT_MAX)
                                 61                 :                :     {
                                 62                 :          18284 :         SET_VARSIZE_SHORT(p, datalen + VARHDRSZ_SHORT);
                                 63         [ +  + ]:          18284 :         if (datalen)
                                 64                 :          18241 :             memcpy(p + VARHDRSZ_SHORT, data, datalen);
                                 65                 :                :     }
                                 66                 :                :     else
                                 67                 :                :     {
 1806 tgl@sss.pgh.pa.us          68                 :UBC           0 :         SET_VARSIZE(p, datalen + VARHDRSZ);
                                 69                 :              0 :         memcpy(p + VARHDRSZ, data, datalen);
                                 70                 :                :     }
                                 71                 :                : 
 1806 tgl@sss.pgh.pa.us          72                 :CBC       18284 :     return PointerGetDatum(p);
                                 73                 :                : }
                                 74                 :                : 
                                 75                 :                : /*
                                 76                 :                :  * Find the length of the common prefix of a and b
                                 77                 :                :  */
                                 78                 :                : static int
                                 79                 :           1051 : commonPrefix(const char *a, const char *b, int lena, int lenb)
                                 80                 :                : {
                                 81                 :           1051 :     int         i = 0;
                                 82                 :                : 
                                 83   [ +  +  +  +  :           2370 :     while (i < lena && i < lenb && *a == *b)
                                              +  + ]
                                 84                 :                :     {
                                 85                 :           1319 :         a++;
                                 86                 :           1319 :         b++;
                                 87                 :           1319 :         i++;
                                 88                 :                :     }
                                 89                 :                : 
                                 90                 :           1051 :     return i;
                                 91                 :                : }
                                 92                 :                : 
                                 93                 :                : /*
                                 94                 :                :  * Binary search an array of int16 datums for a match to c
                                 95                 :                :  *
                                 96                 :                :  * On success, *i gets the match location; on failure, it gets where to insert
                                 97                 :                :  */
                                 98                 :                : static bool
  135 peter@eisentraut.org       99                 :GNC       11473 : searchChar(const Datum *nodeLabels, int nNodes, int16 c, int *i)
                                100                 :                : {
 1806 tgl@sss.pgh.pa.us         101                 :CBC       11473 :     int         StopLow = 0,
                                102                 :          11473 :                 StopHigh = nNodes;
                                103                 :                : 
                                104         [ +  + ]:          36981 :     while (StopLow < StopHigh)
                                105                 :                :     {
                                106                 :          36872 :         int         StopMiddle = (StopLow + StopHigh) >> 1;
                                107                 :          36872 :         int16       middle = DatumGetInt16(nodeLabels[StopMiddle]);
                                108                 :                : 
                                109         [ +  + ]:          36872 :         if (c < middle)
                                110                 :          14901 :             StopHigh = StopMiddle;
                                111         [ +  + ]:          21971 :         else if (c > middle)
                                112                 :          10607 :             StopLow = StopMiddle + 1;
                                113                 :                :         else
                                114                 :                :         {
                                115                 :          11364 :             *i = StopMiddle;
                                116                 :          11364 :             return true;
                                117                 :                :         }
                                118                 :                :     }
                                119                 :                : 
                                120                 :            109 :     *i = StopHigh;
                                121                 :            109 :     return false;
                                122                 :                : }
                                123                 :                : 
                                124                 :              2 : PG_FUNCTION_INFO_V1(spgist_name_choose);
                                125                 :                : Datum
                                126                 :          11477 : spgist_name_choose(PG_FUNCTION_ARGS)
                                127                 :                : {
                                128                 :          11477 :     spgChooseIn *in = (spgChooseIn *) PG_GETARG_POINTER(0);
                                129                 :          11477 :     spgChooseOut *out = (spgChooseOut *) PG_GETARG_POINTER(1);
                                130                 :          11477 :     Name        inName = DatumGetName(in->datum);
                                131                 :          11477 :     char       *inStr = NameStr(*inName);
                                132                 :          11477 :     int         inSize = strlen(inStr);
                                133                 :          11477 :     char       *prefixStr = NULL;
                                134                 :          11477 :     int         prefixSize = 0;
                                135                 :          11477 :     int         commonLen = 0;
                                136                 :          11477 :     int16       nodeChar = 0;
                                137                 :          11477 :     int         i = 0;
                                138                 :                : 
                                139                 :                :     /* Check for prefix match, set nodeChar to first byte after prefix */
                                140         [ +  + ]:          11477 :     if (in->hasPrefix)
                                141                 :                :     {
                                142                 :           1051 :         text       *prefixText = DatumGetTextPP(in->prefixDatum);
                                143                 :                : 
                                144         [ +  - ]:           1051 :         prefixStr = VARDATA_ANY(prefixText);
                                145   [ -  +  -  -  :           1051 :         prefixSize = VARSIZE_ANY_EXHDR(prefixText);
                                     -  -  -  -  +  
                                                 - ]
                                146                 :                : 
                                147                 :           1051 :         commonLen = commonPrefix(inStr + in->level,
                                148                 :                :                                  prefixStr,
                                149                 :           1051 :                                  inSize - in->level,
                                150                 :                :                                  prefixSize);
                                151                 :                : 
                                152         [ +  + ]:           1051 :         if (commonLen == prefixSize)
                                153                 :                :         {
                                154         [ +  + ]:           1047 :             if (inSize - in->level > commonLen)
                                155                 :           1045 :                 nodeChar = *(unsigned char *) (inStr + in->level + commonLen);
                                156                 :                :             else
                                157                 :              2 :                 nodeChar = -1;
                                158                 :                :         }
                                159                 :                :         else
                                160                 :                :         {
                                161                 :                :             /* Must split tuple because incoming value doesn't match prefix */
                                162                 :              4 :             out->resultType = spgSplitTuple;
                                163                 :                : 
                                164         [ +  + ]:              4 :             if (commonLen == 0)
                                165                 :                :             {
                                166                 :              2 :                 out->result.splitTuple.prefixHasPrefix = false;
                                167                 :                :             }
                                168                 :                :             else
                                169                 :                :             {
                                170                 :              2 :                 out->result.splitTuple.prefixHasPrefix = true;
                                171                 :              2 :                 out->result.splitTuple.prefixPrefixDatum =
                                172                 :              2 :                     formTextDatum(prefixStr, commonLen);
                                173                 :                :             }
                                174                 :              4 :             out->result.splitTuple.prefixNNodes = 1;
                                175                 :              4 :             out->result.splitTuple.prefixNodeLabels =
   96 michael@paquier.xyz       176                 :GNC           4 :                 palloc_object(Datum);
 1806 tgl@sss.pgh.pa.us         177                 :CBC           8 :             out->result.splitTuple.prefixNodeLabels[0] =
                                178                 :              4 :                 Int16GetDatum(*(unsigned char *) (prefixStr + commonLen));
                                179                 :                : 
                                180                 :              4 :             out->result.splitTuple.childNodeN = 0;
                                181                 :                : 
                                182         [ +  - ]:              4 :             if (prefixSize - commonLen == 1)
                                183                 :                :             {
                                184                 :              4 :                 out->result.splitTuple.postfixHasPrefix = false;
                                185                 :                :             }
                                186                 :                :             else
                                187                 :                :             {
 1806 tgl@sss.pgh.pa.us         188                 :LBC         (2) :                 out->result.splitTuple.postfixHasPrefix = true;
                                189                 :            (2) :                 out->result.splitTuple.postfixPrefixDatum =
                                190                 :            (2) :                     formTextDatum(prefixStr + commonLen + 1,
                                191                 :            (2) :                                   prefixSize - commonLen - 1);
                                192                 :                :             }
                                193                 :                : 
 1806 tgl@sss.pgh.pa.us         194                 :CBC           4 :             PG_RETURN_VOID();
                                195                 :                :         }
                                196                 :                :     }
                                197         [ +  + ]:          10426 :     else if (inSize > in->level)
                                198                 :                :     {
                                199                 :          10406 :         nodeChar = *(unsigned char *) (inStr + in->level);
                                200                 :                :     }
                                201                 :                :     else
                                202                 :                :     {
                                203                 :             20 :         nodeChar = -1;
                                204                 :                :     }
                                205                 :                : 
                                206                 :                :     /* Look up nodeChar in the node label array */
                                207         [ +  + ]:          11473 :     if (searchChar(in->nodeLabels, in->nNodes, nodeChar, &i))
                                208                 :                :     {
                                209                 :                :         /*
                                210                 :                :          * Descend to existing node.  (If in->allTheSame, the core code will
                                211                 :                :          * ignore our nodeN specification here, but that's OK.  We still have
                                212                 :                :          * to provide the correct levelAdd and restDatum values, and those are
                                213                 :                :          * the same regardless of which node gets chosen by core.)
                                214                 :                :          */
                                215                 :                :         int         levelAdd;
                                216                 :                : 
                                217                 :          11364 :         out->resultType = spgMatchNode;
                                218                 :          11364 :         out->result.matchNode.nodeN = i;
                                219                 :          11364 :         levelAdd = commonLen;
                                220         [ +  + ]:          11364 :         if (nodeChar >= 0)
                                221                 :          11342 :             levelAdd++;
                                222                 :          11364 :         out->result.matchNode.levelAdd = levelAdd;
                                223         [ +  + ]:          11364 :         if (inSize - in->level - levelAdd > 0)
                                224                 :          11321 :             out->result.matchNode.restDatum =
                                225                 :          11321 :                 formTextDatum(inStr + in->level + levelAdd,
                                226                 :          11321 :                               inSize - in->level - levelAdd);
                                227                 :                :         else
                                228                 :             43 :             out->result.matchNode.restDatum =
                                229                 :             43 :                 formTextDatum(NULL, 0);
                                230                 :                :     }
                                231         [ -  + ]:            109 :     else if (in->allTheSame)
                                232                 :                :     {
                                233                 :                :         /*
                                234                 :                :          * Can't use AddNode action, so split the tuple.  The upper tuple has
                                235                 :                :          * the same prefix as before and uses a dummy node label -2 for the
                                236                 :                :          * lower tuple.  The lower tuple has no prefix and the same node
                                237                 :                :          * labels as the original tuple.
                                238                 :                :          *
                                239                 :                :          * Note: it might seem tempting to shorten the upper tuple's prefix,
                                240                 :                :          * if it has one, then use its last byte as label for the lower tuple.
                                241                 :                :          * But that doesn't win since we know the incoming value matches the
                                242                 :                :          * whole prefix: we'd just end up splitting the lower tuple again.
                                243                 :                :          */
 1806 tgl@sss.pgh.pa.us         244                 :UBC           0 :         out->resultType = spgSplitTuple;
                                245                 :              0 :         out->result.splitTuple.prefixHasPrefix = in->hasPrefix;
                                246                 :              0 :         out->result.splitTuple.prefixPrefixDatum = in->prefixDatum;
                                247                 :              0 :         out->result.splitTuple.prefixNNodes = 1;
   96 michael@paquier.xyz       248                 :UNC           0 :         out->result.splitTuple.prefixNodeLabels = palloc_object(Datum);
 1806 tgl@sss.pgh.pa.us         249                 :UBC           0 :         out->result.splitTuple.prefixNodeLabels[0] = Int16GetDatum(-2);
                                250                 :              0 :         out->result.splitTuple.childNodeN = 0;
                                251                 :              0 :         out->result.splitTuple.postfixHasPrefix = false;
                                252                 :                :     }
                                253                 :                :     else
                                254                 :                :     {
                                255                 :                :         /* Add a node for the not-previously-seen nodeChar value */
 1806 tgl@sss.pgh.pa.us         256                 :CBC         109 :         out->resultType = spgAddNode;
                                257                 :            109 :         out->result.addNode.nodeLabel = Int16GetDatum(nodeChar);
                                258                 :            109 :         out->result.addNode.nodeN = i;
                                259                 :                :     }
                                260                 :                : 
                                261                 :          11473 :     PG_RETURN_VOID();
                                262                 :                : }
                                263                 :                : 
                                264                 :                : /* The picksplit function is identical to the core opclass, so just use that */
                                265                 :                : 
                                266                 :              2 : PG_FUNCTION_INFO_V1(spgist_name_inner_consistent);
                                267                 :                : Datum
                                268                 :              4 : spgist_name_inner_consistent(PG_FUNCTION_ARGS)
                                269                 :                : {
                                270                 :              4 :     spgInnerConsistentIn *in = (spgInnerConsistentIn *) PG_GETARG_POINTER(0);
                                271                 :              4 :     spgInnerConsistentOut *out = (spgInnerConsistentOut *) PG_GETARG_POINTER(1);
                                272                 :                :     text       *reconstructedValue;
                                273                 :                :     text       *reconstrText;
                                274                 :                :     int         maxReconstrLen;
                                275                 :              4 :     text       *prefixText = NULL;
                                276                 :              4 :     int         prefixSize = 0;
                                277                 :                :     int         i;
                                278                 :                : 
                                279                 :                :     /*
                                280                 :                :      * Reconstruct values represented at this tuple, including parent data,
                                281                 :                :      * prefix of this tuple if any, and the node label if it's non-dummy.
                                282                 :                :      * in->level should be the length of the previously reconstructed value,
                                283                 :                :      * and the number of bytes added here is prefixSize or prefixSize + 1.
                                284                 :                :      *
                                285                 :                :      * Recall that reconstructedValues are assumed to be the same type as leaf
                                286                 :                :      * datums, so we must use "text" not "name" for them.
                                287                 :                :      *
                                288                 :                :      * Note: we assume that in->reconstructedValue isn't toasted and doesn't
                                289                 :                :      * have a short varlena header.  This is okay because it must have been
                                290                 :                :      * created by a previous invocation of this routine, and we always emit
                                291                 :                :      * long-format reconstructed values.
                                292                 :                :      */
                                293                 :              4 :     reconstructedValue = (text *) DatumGetPointer(in->reconstructedValue);
                                294   [ +  +  -  +  :              4 :     Assert(reconstructedValue == NULL ? in->level == 0 :
                                     -  -  -  -  -  
                                        -  -  +  -  
                                                 + ]
                                295                 :                :            VARSIZE_ANY_EXHDR(reconstructedValue) == in->level);
                                296                 :                : 
                                297                 :              4 :     maxReconstrLen = in->level + 1;
                                298         [ -  + ]:              4 :     if (in->hasPrefix)
                                299                 :                :     {
 1806 tgl@sss.pgh.pa.us         300                 :UBC           0 :         prefixText = DatumGetTextPP(in->prefixDatum);
                                301   [ #  #  #  #  :              0 :         prefixSize = VARSIZE_ANY_EXHDR(prefixText);
                                     #  #  #  #  #  
                                                 # ]
                                302                 :              0 :         maxReconstrLen += prefixSize;
                                303                 :                :     }
                                304                 :                : 
 1806 tgl@sss.pgh.pa.us         305                 :CBC           4 :     reconstrText = palloc(VARHDRSZ + maxReconstrLen);
                                306                 :              4 :     SET_VARSIZE(reconstrText, VARHDRSZ + maxReconstrLen);
                                307                 :                : 
                                308         [ +  + ]:              4 :     if (in->level)
                                309                 :              2 :         memcpy(VARDATA(reconstrText),
                                310                 :              2 :                VARDATA(reconstructedValue),
                                311                 :              2 :                in->level);
                                312         [ -  + ]:              4 :     if (prefixSize)
 1806 tgl@sss.pgh.pa.us         313                 :UBC           0 :         memcpy(((char *) VARDATA(reconstrText)) + in->level,
                                314         [ #  # ]:              0 :                VARDATA_ANY(prefixText),
                                315                 :                :                prefixSize);
                                316                 :                :     /* last byte of reconstrText will be filled in below */
                                317                 :                : 
                                318                 :                :     /*
                                319                 :                :      * Scan the child nodes.  For each one, complete the reconstructed value
                                320                 :                :      * and see if it's consistent with the query.  If so, emit an entry into
                                321                 :                :      * the output arrays.
                                322                 :                :      */
   96 michael@paquier.xyz       323                 :GNC           4 :     out->nodeNumbers = palloc_array(int, in->nNodes);
                                324                 :              4 :     out->levelAdds = palloc_array(int, in->nNodes);
                                325                 :              4 :     out->reconstructedValues = palloc_array(Datum, in->nNodes);
 1806 tgl@sss.pgh.pa.us         326                 :CBC           4 :     out->nNodes = 0;
                                327                 :                : 
                                328         [ +  + ]:             70 :     for (i = 0; i < in->nNodes; i++)
                                329                 :                :     {
                                330                 :             66 :         int16       nodeChar = DatumGetInt16(in->nodeLabels[i]);
                                331                 :                :         int         thisLen;
                                332                 :             66 :         bool        res = true;
                                333                 :                :         int         j;
                                334                 :                : 
                                335                 :                :         /* If nodeChar is a dummy value, don't include it in data */
                                336         [ -  + ]:             66 :         if (nodeChar <= 0)
 1806 tgl@sss.pgh.pa.us         337                 :UBC           0 :             thisLen = maxReconstrLen - 1;
                                338                 :                :         else
                                339                 :                :         {
 1806 tgl@sss.pgh.pa.us         340                 :CBC          66 :             ((unsigned char *) VARDATA(reconstrText))[maxReconstrLen - 1] = nodeChar;
                                341                 :             66 :             thisLen = maxReconstrLen;
                                342                 :                :         }
                                343                 :                : 
                                344         [ +  + ]:            128 :         for (j = 0; j < in->nkeys; j++)
                                345                 :                :         {
                                346                 :            124 :             StrategyNumber strategy = in->scankeys[j].sk_strategy;
                                347                 :                :             Name        inName;
                                348                 :                :             char       *inStr;
                                349                 :                :             int         inSize;
                                350                 :                :             int         r;
                                351                 :                : 
                                352                 :            124 :             inName = DatumGetName(in->scankeys[j].sk_argument);
                                353                 :            124 :             inStr = NameStr(*inName);
                                354                 :            124 :             inSize = strlen(inStr);
                                355                 :                : 
                                356                 :            248 :             r = memcmp(VARDATA(reconstrText), inStr,
                                357                 :            124 :                        Min(inSize, thisLen));
                                358                 :                : 
                                359   [ +  -  +  - ]:            124 :             switch (strategy)
                                360                 :                :             {
                                361                 :             58 :                 case BTLessStrategyNumber:
                                362                 :                :                 case BTLessEqualStrategyNumber:
                                363         [ +  + ]:             58 :                     if (r > 0)
                                364                 :             54 :                         res = false;
                                365                 :             58 :                     break;
 1806 tgl@sss.pgh.pa.us         366                 :UBC           0 :                 case BTEqualStrategyNumber:
                                367   [ #  #  #  # ]:              0 :                     if (r != 0 || inSize < thisLen)
                                368                 :              0 :                         res = false;
                                369                 :              0 :                     break;
 1806 tgl@sss.pgh.pa.us         370                 :CBC          66 :                 case BTGreaterEqualStrategyNumber:
                                371                 :                :                 case BTGreaterStrategyNumber:
                                372         [ +  + ]:             66 :                     if (r < 0)
                                373                 :              8 :                         res = false;
                                374                 :             66 :                     break;
 1806 tgl@sss.pgh.pa.us         375                 :UBC           0 :                 default:
                                376         [ #  # ]:              0 :                     elog(ERROR, "unrecognized strategy number: %d",
                                377                 :                :                          in->scankeys[j].sk_strategy);
                                378                 :                :                     break;
                                379                 :                :             }
                                380                 :                : 
 1806 tgl@sss.pgh.pa.us         381         [ +  + ]:CBC         124 :             if (!res)
                                382                 :             62 :                 break;          /* no need to consider remaining conditions */
                                383                 :                :         }
                                384                 :                : 
                                385         [ +  + ]:             66 :         if (res)
                                386                 :                :         {
                                387                 :              4 :             out->nodeNumbers[out->nNodes] = i;
                                388                 :              4 :             out->levelAdds[out->nNodes] = thisLen - in->level;
                                389                 :              4 :             SET_VARSIZE(reconstrText, VARHDRSZ + thisLen);
                                390                 :              8 :             out->reconstructedValues[out->nNodes] =
                                391                 :              4 :                 datumCopy(PointerGetDatum(reconstrText), false, -1);
                                392                 :              4 :             out->nNodes++;
                                393                 :                :         }
                                394                 :                :     }
                                395                 :                : 
                                396                 :              4 :     PG_RETURN_VOID();
                                397                 :                : }
                                398                 :                : 
                                399                 :              2 : PG_FUNCTION_INFO_V1(spgist_name_leaf_consistent);
                                400                 :                : Datum
                                401                 :            126 : spgist_name_leaf_consistent(PG_FUNCTION_ARGS)
                                402                 :                : {
                                403                 :            126 :     spgLeafConsistentIn *in = (spgLeafConsistentIn *) PG_GETARG_POINTER(0);
                                404                 :            126 :     spgLeafConsistentOut *out = (spgLeafConsistentOut *) PG_GETARG_POINTER(1);
                                405                 :            126 :     int         level = in->level;
                                406                 :                :     text       *leafValue,
                                407                 :            126 :                *reconstrValue = NULL;
                                408                 :                :     char       *fullValue;
                                409                 :                :     int         fullLen;
                                410                 :                :     bool        res;
                                411                 :                :     int         j;
                                412                 :                : 
                                413                 :                :     /* all tests are exact */
                                414                 :            126 :     out->recheck = false;
                                415                 :                : 
                                416                 :            126 :     leafValue = DatumGetTextPP(in->leafDatum);
                                417                 :                : 
                                418                 :                :     /* As above, in->reconstructedValue isn't toasted or short. */
                                419         [ +  - ]:            126 :     if (DatumGetPointer(in->reconstructedValue))
                                420                 :            126 :         reconstrValue = (text *) DatumGetPointer(in->reconstructedValue);
                                421                 :                : 
                                422   [ -  +  -  +  :            126 :     Assert(reconstrValue == NULL ? level == 0 :
                                     -  -  -  -  -  
                                        -  -  +  -  
                                                 + ]
                                423                 :                :            VARSIZE_ANY_EXHDR(reconstrValue) == level);
                                424                 :                : 
                                425                 :                :     /* Reconstruct the Name represented by this leaf tuple */
                                426                 :            126 :     fullValue = palloc0(NAMEDATALEN);
                                427   [ -  +  -  -  :            126 :     fullLen = level + VARSIZE_ANY_EXHDR(leafValue);
                                     -  -  -  -  +  
                                                 - ]
                                428         [ -  + ]:            126 :     Assert(fullLen < NAMEDATALEN);
                                429   [ -  +  -  -  :            126 :     if (VARSIZE_ANY_EXHDR(leafValue) == 0 && level > 0)
                                     -  -  -  -  +  
                                     -  -  +  -  -  
                                              -  - ]
                                430                 :                :     {
 1806 tgl@sss.pgh.pa.us         431                 :UBC           0 :         memcpy(fullValue, VARDATA(reconstrValue),
 1806 tgl@sss.pgh.pa.us         432   [ #  #  #  #  :EUB             :                VARSIZE_ANY_EXHDR(reconstrValue));
                                     #  #  #  #  #  
                                                 # ]
                                433                 :                :     }
                                434                 :                :     else
                                435                 :                :     {
 1806 tgl@sss.pgh.pa.us         436         [ +  - ]:CBC         126 :         if (level)
                                437                 :            126 :             memcpy(fullValue, VARDATA(reconstrValue), level);
                                438   [ +  -  -  -  :            126 :         if (VARSIZE_ANY_EXHDR(leafValue) > 0)
                                     -  -  -  -  +  
                                           -  +  - ]
                                439         [ +  - ]:            126 :             memcpy(fullValue + level, VARDATA_ANY(leafValue),
 1806 tgl@sss.pgh.pa.us         440   [ -  +  -  -  :ECB       (124) :                    VARSIZE_ANY_EXHDR(leafValue));
                                     -  -  -  -  +  
                                                 - ]
                                441                 :                :     }
 1806 tgl@sss.pgh.pa.us         442                 :CBC         126 :     out->leafValue = PointerGetDatum(fullValue);
                                443                 :                : 
                                444                 :                :     /* Perform the required comparison(s) */
                                445                 :            126 :     res = true;
                                446         [ +  + ]:            260 :     for (j = 0; j < in->nkeys; j++)
                                447                 :                :     {
                                448                 :            234 :         StrategyNumber strategy = in->scankeys[j].sk_strategy;
                                449                 :            234 :         Name        queryName = DatumGetName(in->scankeys[j].sk_argument);
                                450                 :            234 :         char       *queryStr = NameStr(*queryName);
                                451                 :            234 :         int         queryLen = strlen(queryStr);
                                452                 :                :         int         r;
                                453                 :                : 
                                454                 :                :         /* Non-collation-aware comparison */
                                455                 :            234 :         r = memcmp(fullValue, queryStr, Min(queryLen, fullLen));
                                456                 :                : 
                                457         [ +  + ]:            234 :         if (r == 0)
                                458                 :                :         {
                                459         [ -  + ]:             26 :             if (queryLen > fullLen)
 1806 tgl@sss.pgh.pa.us         460                 :UBC           0 :                 r = -1;
 1806 tgl@sss.pgh.pa.us         461         [ +  - ]:CBC          26 :             else if (queryLen < fullLen)
                                462                 :             26 :                 r = 1;
                                463                 :                :         }
                                464                 :                : 
                                465   [ +  -  -  -  :            234 :         switch (strategy)
                                              +  - ]
                                466                 :                :         {
                                467                 :            108 :             case BTLessStrategyNumber:
                                468                 :            108 :                 res = (r < 0);
                                469                 :            108 :                 break;
 1806 tgl@sss.pgh.pa.us         470                 :UBC           0 :             case BTLessEqualStrategyNumber:
                                471                 :              0 :                 res = (r <= 0);
                                472                 :              0 :                 break;
                                473                 :              0 :             case BTEqualStrategyNumber:
                                474                 :              0 :                 res = (r == 0);
                                475                 :              0 :                 break;
                                476                 :              0 :             case BTGreaterEqualStrategyNumber:
                                477                 :              0 :                 res = (r >= 0);
                                478                 :              0 :                 break;
 1806 tgl@sss.pgh.pa.us         479                 :CBC         126 :             case BTGreaterStrategyNumber:
                                480                 :            126 :                 res = (r > 0);
                                481                 :            126 :                 break;
 1806 tgl@sss.pgh.pa.us         482                 :UBC           0 :             default:
                                483         [ #  # ]:              0 :                 elog(ERROR, "unrecognized strategy number: %d",
                                484                 :                :                      in->scankeys[j].sk_strategy);
                                485                 :                :                 res = false;
                                486                 :                :                 break;
                                487                 :                :         }
                                488                 :                : 
 1806 tgl@sss.pgh.pa.us         489         [ +  + ]:CBC         234 :         if (!res)
                                490                 :            100 :             break;              /* no need to consider remaining conditions */
                                491                 :                :     }
                                492                 :                : 
                                493                 :            126 :     PG_RETURN_BOOL(res);
                                494                 :                : }
                                495                 :                : 
                                496                 :              2 : PG_FUNCTION_INFO_V1(spgist_name_compress);
                                497                 :                : Datum
                                498                 :           6918 : spgist_name_compress(PG_FUNCTION_ARGS)
                                499                 :                : {
                                500                 :           6918 :     Name        inName = PG_GETARG_NAME(0);
                                501                 :           6918 :     char       *inStr = NameStr(*inName);
                                502                 :                : 
                                503                 :           6918 :     PG_RETURN_DATUM(formTextDatum(inStr, strlen(inStr)));
                                504                 :                : }
        

Generated by: LCOV version 2.4-beta