LCOV - differential code coverage report
Current view: top level - src/backend/access/gin - ginscan.c (source / functions) Coverage Total Hit UIC UBC GBC GIC GNC CBC DCB
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 93.6 % 188 176 12 1 175 1
Current Date: 2024-04-14 14:21:10 Functions: 100.0 % 8 8 1 7
Baseline: 16@8cea358b128 Branches: 77.0 % 100 77 1 22 1 3 73
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed (120,180] days: 100.0 % 1 1 1
(240..) days: 93.6 % 187 175 12 175
Function coverage date bins:
(240..) days: 100.0 % 8 8 1 7
Branch coverage date bins:
(240..) days: 77.0 % 100 77 1 22 1 3 73

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * ginscan.c
                                  4                 :                :  *    routines to manage scans of inverted index relations
                                  5                 :                :  *
                                  6                 :                :  *
                                  7                 :                :  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
                                  8                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                  9                 :                :  *
                                 10                 :                :  * IDENTIFICATION
                                 11                 :                :  *          src/backend/access/gin/ginscan.c
                                 12                 :                :  *-------------------------------------------------------------------------
                                 13                 :                :  */
                                 14                 :                : 
                                 15                 :                : #include "postgres.h"
                                 16                 :                : 
                                 17                 :                : #include "access/gin_private.h"
                                 18                 :                : #include "access/relscan.h"
                                 19                 :                : #include "pgstat.h"
                                 20                 :                : #include "utils/memutils.h"
                                 21                 :                : #include "utils/rel.h"
                                 22                 :                : 
                                 23                 :                : 
                                 24                 :                : IndexScanDesc
 3010 tgl@sss.pgh.pa.us          25                 :CBC         796 : ginbeginscan(Relation rel, int nkeys, int norderbys)
                                 26                 :                : {
                                 27                 :                :     IndexScanDesc scan;
                                 28                 :                :     GinScanOpaque so;
                                 29                 :                : 
                                 30                 :                :     /* no order by operators allowed */
 4882                            31         [ -  + ]:            796 :     Assert(norderbys == 0);
                                 32                 :                : 
                                 33                 :            796 :     scan = RelationGetIndexScan(rel, nkeys, norderbys);
                                 34                 :                : 
                                 35                 :                :     /* allocate private workspace */
                                 36                 :            796 :     so = (GinScanOpaque) palloc(sizeof(GinScanOpaqueData));
                                 37                 :            796 :     so->keys = NULL;
                                 38                 :            796 :     so->nkeys = 0;
                                 39                 :            796 :     so->tempCtx = AllocSetContextCreate(CurrentMemoryContext,
                                 40                 :                :                                         "Gin scan temporary context",
                                 41                 :                :                                         ALLOCSET_DEFAULT_SIZES);
 3357 heikki.linnakangas@i       42                 :            796 :     so->keyCtx = AllocSetContextCreate(CurrentMemoryContext,
                                 43                 :                :                                        "Gin scan key context",
                                 44                 :                :                                        ALLOCSET_DEFAULT_SIZES);
 4882 tgl@sss.pgh.pa.us          45                 :            796 :     initGinState(&so->ginstate, scan->indexRelation);
                                 46                 :                : 
                                 47                 :            796 :     scan->opaque = so;
                                 48                 :                : 
 3010                            49                 :            796 :     return scan;
                                 50                 :                : }
                                 51                 :                : 
                                 52                 :                : /*
                                 53                 :                :  * Create a new GinScanEntry, unless an equivalent one already exists,
                                 54                 :                :  * in which case just return it
                                 55                 :                :  */
                                 56                 :                : static GinScanEntry
 4845                            57                 :           3346 : ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
                                 58                 :                :                  StrategyNumber strategy, int32 searchMode,
                                 59                 :                :                  Datum queryKey, GinNullCategory queryCategory,
                                 60                 :                :                  bool isPartialMatch, Pointer extra_data)
                                 61                 :                : {
                                 62                 :           3346 :     GinState   *ginstate = &so->ginstate;
                                 63                 :                :     GinScanEntry scanEntry;
                                 64                 :                :     uint32      i;
                                 65                 :                : 
                                 66                 :                :     /*
                                 67                 :                :      * Look for an existing equivalent entry.
                                 68                 :                :      *
                                 69                 :                :      * Entries with non-null extra_data are never considered identical, since
                                 70                 :                :      * we can't know exactly what the opclass might be doing with that.
                                 71                 :                :      */
                                 72         [ +  + ]:           3346 :     if (extra_data == NULL)
                                 73                 :                :     {
                                 74         [ +  + ]:         228505 :         for (i = 0; i < so->totalentries; i++)
                                 75                 :                :         {
                                 76                 :         226000 :             GinScanEntry prevEntry = so->entries[i];
                                 77                 :                : 
                                 78         [ +  + ]:         226000 :             if (prevEntry->extra_data == NULL &&
                                 79         [ +  - ]:         225850 :                 prevEntry->isPartialMatch == isPartialMatch &&
                                 80         [ +  + ]:         225850 :                 prevEntry->strategy == strategy &&
                                 81         [ +  - ]:         225780 :                 prevEntry->searchMode == searchMode &&
                                 82   [ +  +  -  + ]:         451548 :                 prevEntry->attnum == attnum &&
                                 83                 :         225768 :                 ginCompareEntries(ginstate, attnum,
                                 84                 :                :                                   prevEntry->queryKey,
                                 85                 :         225768 :                                   prevEntry->queryCategory,
                                 86                 :                :                                   queryKey,
                                 87                 :                :                                   queryCategory) == 0)
                                 88                 :                :             {
                                 89                 :                :                 /* Successful match */
 4845 tgl@sss.pgh.pa.us          90                 :UBC           0 :                 return prevEntry;
                                 91                 :                :             }
                                 92                 :                :         }
                                 93                 :                :     }
                                 94                 :                : 
                                 95                 :                :     /* Nope, create a new entry */
 4845 tgl@sss.pgh.pa.us          96                 :CBC        3346 :     scanEntry = (GinScanEntry) palloc(sizeof(GinScanEntryData));
                                 97                 :           3346 :     scanEntry->queryKey = queryKey;
                                 98                 :           3346 :     scanEntry->queryCategory = queryCategory;
                                 99                 :           3346 :     scanEntry->isPartialMatch = isPartialMatch;
                                100                 :           3346 :     scanEntry->extra_data = extra_data;
                                101                 :           3346 :     scanEntry->strategy = strategy;
                                102                 :           3346 :     scanEntry->searchMode = searchMode;
                                103                 :           3346 :     scanEntry->attnum = attnum;
                                104                 :                : 
                                105                 :           3346 :     scanEntry->buffer = InvalidBuffer;
                                106                 :           3346 :     ItemPointerSetMin(&scanEntry->curItem);
                                107                 :           3346 :     scanEntry->matchBitmap = NULL;
                                108                 :           3346 :     scanEntry->matchIterator = NULL;
                                109                 :           3346 :     scanEntry->matchResult = NULL;
                                110                 :           3346 :     scanEntry->list = NULL;
                                111                 :           3346 :     scanEntry->nlist = 0;
                                112                 :           3346 :     scanEntry->offset = InvalidOffsetNumber;
                                113                 :           3346 :     scanEntry->isFinished = false;
                                114                 :           3346 :     scanEntry->reduceResult = false;
                                115                 :                : 
                                116                 :                :     /* Add it to so's array */
                                117         [ +  + ]:           3346 :     if (so->totalentries >= so->allocentries)
                                118                 :                :     {
                                119                 :             23 :         so->allocentries *= 2;
                                120                 :             23 :         so->entries = (GinScanEntry *)
                                121                 :             23 :             repalloc(so->entries, so->allocentries * sizeof(GinScanEntry));
                                122                 :                :     }
                                123                 :           3346 :     so->entries[so->totalentries++] = scanEntry;
                                124                 :                : 
                                125                 :           3346 :     return scanEntry;
                                126                 :                : }
                                127                 :                : 
                                128                 :                : /*
                                129                 :                :  * Append hidden scan entry of given category to the scan key.
                                130                 :                :  *
                                131                 :                :  * NB: this had better be called at most once per scan key, since
                                132                 :                :  * ginFillScanKey leaves room for only one hidden entry.  Currently,
                                133                 :                :  * it seems sufficiently clear that this is true that we don't bother
                                134                 :                :  * with any cross-check logic.
                                135                 :                :  */
                                136                 :                : static void
 1548 akorotkov@postgresql      137                 :            163 : ginScanKeyAddHiddenEntry(GinScanOpaque so, GinScanKey key,
                                138                 :                :                          GinNullCategory queryCategory)
                                139                 :                : {
                                140                 :            163 :     int         i = key->nentries++;
                                141                 :                : 
                                142                 :                :     /* strategy is of no interest because this is not a partial-match item */
                                143                 :            163 :     key->scanEntry[i] = ginFillScanEntry(so, key->attnum,
                                144                 :                :                                          InvalidStrategy, key->searchMode,
                                145                 :                :                                          (Datum) 0, queryCategory,
                                146                 :                :                                          false, NULL);
                                147                 :            163 : }
                                148                 :                : 
                                149                 :                : /*
                                150                 :                :  * Initialize the next GinScanKey using the output from the extractQueryFn
                                151                 :                :  */
                                152                 :                : static void
 4845 tgl@sss.pgh.pa.us         153                 :            857 : ginFillScanKey(GinScanOpaque so, OffsetNumber attnum,
                                154                 :                :                StrategyNumber strategy, int32 searchMode,
                                155                 :                :                Datum query, uint32 nQueryValues,
                                156                 :                :                Datum *queryValues, GinNullCategory *queryCategories,
                                157                 :                :                bool *partial_matches, Pointer *extra_data)
                                158                 :                : {
                                159                 :            857 :     GinScanKey  key = &(so->keys[so->nkeys++]);
                                160                 :            857 :     GinState   *ginstate = &so->ginstate;
                                161                 :                :     uint32      i;
                                162                 :                : 
 4846                           163                 :            857 :     key->nentries = nQueryValues;
 1548 akorotkov@postgresql      164                 :            857 :     key->nuserentries = nQueryValues;
                                165                 :                : 
                                166                 :                :     /* Allocate one extra array slot for possible "hidden" entry */
                                167                 :           1714 :     key->scanEntry = (GinScanEntry *) palloc(sizeof(GinScanEntry) *
                                168                 :            857 :                                              (nQueryValues + 1));
                                169                 :           1714 :     key->entryRes = (GinTernaryValue *) palloc0(sizeof(GinTernaryValue) *
                                170                 :            857 :                                                 (nQueryValues + 1));
                                171                 :                : 
 4846 tgl@sss.pgh.pa.us         172                 :            857 :     key->query = query;
                                173                 :            857 :     key->queryValues = queryValues;
                                174                 :            857 :     key->queryCategories = queryCategories;
                                175                 :            857 :     key->extra_data = extra_data;
 6557 teodor@sigaev.ru          176                 :            857 :     key->strategy = strategy;
 4846 tgl@sss.pgh.pa.us         177                 :            857 :     key->searchMode = searchMode;
 5756                           178                 :            857 :     key->attnum = attnum;
                                179                 :                : 
                                180                 :                :     /*
                                181                 :                :      * Initially, scan keys of GIN_SEARCH_MODE_ALL mode are marked
                                182                 :                :      * excludeOnly.  This might get changed later.
                                183                 :                :      */
 1548 akorotkov@postgresql      184                 :            857 :     key->excludeOnly = (searchMode == GIN_SEARCH_MODE_ALL);
                                185                 :                : 
 5006 tgl@sss.pgh.pa.us         186                 :            857 :     ItemPointerSetMin(&key->curItem);
 4845                           187                 :            857 :     key->curItemMatches = false;
                                188                 :            857 :     key->recheckCurItem = false;
                                189                 :            857 :     key->isFinished = false;
 3362 heikki.linnakangas@i      190                 :            857 :     key->nrequired = 0;
                                191                 :            857 :     key->nadditional = 0;
                                192                 :            857 :     key->requiredEntries = NULL;
                                193                 :            857 :     key->additionalEntries = NULL;
                                194                 :                : 
 3719                           195                 :            857 :     ginInitConsistentFunction(ginstate, key);
                                196                 :                : 
                                197                 :                :     /* Set up normal scan entries using extractQueryFn's outputs */
 4846 tgl@sss.pgh.pa.us         198         [ +  + ]:           4040 :     for (i = 0; i < nQueryValues; i++)
                                199                 :                :     {
                                200                 :                :         Datum       queryKey;
                                201                 :                :         GinNullCategory queryCategory;
                                202                 :                :         bool        isPartialMatch;
                                203                 :                :         Pointer     this_extra;
                                204                 :                : 
 1548 akorotkov@postgresql      205                 :           3183 :         queryKey = queryValues[i];
                                206                 :           3183 :         queryCategory = queryCategories[i];
                                207                 :           3183 :         isPartialMatch =
                                208   [ +  +  +  - ]:           3183 :             (ginstate->canPartialMatch[attnum - 1] && partial_matches)
                                209   [ +  +  +  + ]:           3183 :             ? partial_matches[i] : false;
                                210         [ +  + ]:           3183 :         this_extra = (extra_data) ? extra_data[i] : NULL;
                                211                 :                : 
 4845 tgl@sss.pgh.pa.us         212                 :           3183 :         key->scanEntry[i] = ginFillScanEntry(so, attnum,
                                213                 :                :                                              strategy, searchMode,
                                214                 :                :                                              queryKey, queryCategory,
                                215                 :                :                                              isPartialMatch, this_extra);
                                216                 :                :     }
                                217                 :                : 
                                218                 :                :     /*
                                219                 :                :      * For GIN_SEARCH_MODE_INCLUDE_EMPTY and GIN_SEARCH_MODE_EVERYTHING search
                                220                 :                :      * modes, we add the "hidden" entry immediately.  GIN_SEARCH_MODE_ALL is
                                221                 :                :      * handled later, since we might be able to omit the hidden entry for it.
                                222                 :                :      */
 1548 akorotkov@postgresql      223         [ +  + ]:            857 :     if (searchMode == GIN_SEARCH_MODE_INCLUDE_EMPTY)
                                224                 :             22 :         ginScanKeyAddHiddenEntry(so, key, GIN_CAT_EMPTY_ITEM);
                                225         [ -  + ]:            835 :     else if (searchMode == GIN_SEARCH_MODE_EVERYTHING)
 1548 akorotkov@postgresql      226                 :UBC           0 :         ginScanKeyAddHiddenEntry(so, key, GIN_CAT_EMPTY_QUERY);
 6557 teodor@sigaev.ru          227                 :CBC         857 : }
                                228                 :                : 
                                229                 :                : /*
                                230                 :                :  * Release current scan keys, if any.
                                231                 :                :  */
                                232                 :                : void
 3362 heikki.linnakangas@i      233                 :           2394 : ginFreeScanKeys(GinScanOpaque so)
                                234                 :                : {
                                235                 :                :     uint32      i;
                                236                 :                : 
 4845 tgl@sss.pgh.pa.us         237         [ +  + ]:           2394 :     if (so->keys == NULL)
 6557 teodor@sigaev.ru          238                 :           1595 :         return;
                                239                 :                : 
 4845 tgl@sss.pgh.pa.us         240         [ +  + ]:           4145 :     for (i = 0; i < so->totalentries; i++)
                                241                 :                :     {
                                242                 :           3346 :         GinScanEntry entry = so->entries[i];
                                243                 :                : 
                                244         [ -  + ]:           3346 :         if (entry->buffer != InvalidBuffer)
 4845 tgl@sss.pgh.pa.us         245                 :UBC           0 :             ReleaseBuffer(entry->buffer);
 2954 tgl@sss.pgh.pa.us         246         [ +  + ]:CBC        3346 :         if (entry->list)
                                247                 :           2218 :             pfree(entry->list);
 4845                           248         [ -  + ]:           3346 :         if (entry->matchIterator)
 4845 tgl@sss.pgh.pa.us         249                 :UBC           0 :             tbm_end_iterate(entry->matchIterator);
 4845 tgl@sss.pgh.pa.us         250         [ +  + ]:CBC        3346 :         if (entry->matchBitmap)
                                251                 :            267 :             tbm_free(entry->matchBitmap);
                                252                 :                :     }
                                253                 :                : 
  151 nathan@postgresql.or      254                 :GNC         799 :     MemoryContextReset(so->keyCtx);
                                255                 :                : 
 3357 heikki.linnakangas@i      256                 :CBC         799 :     so->keys = NULL;
                                257                 :            799 :     so->nkeys = 0;
 4845 tgl@sss.pgh.pa.us         258                 :            799 :     so->entries = NULL;
                                259                 :            799 :     so->totalentries = 0;
                                260                 :                : }
                                261                 :                : 
                                262                 :                : void
 4928                           263                 :            799 : ginNewScanKey(IndexScanDesc scan)
                                264                 :                : {
 6402 bruce@momjian.us          265                 :            799 :     ScanKey     scankey = scan->keyData;
 6557 teodor@sigaev.ru          266                 :            799 :     GinScanOpaque so = (GinScanOpaque) scan->opaque;
                                267                 :                :     int         i;
 4846 tgl@sss.pgh.pa.us         268                 :            799 :     bool        hasNullQuery = false;
 1548 akorotkov@postgresql      269                 :            799 :     bool        attrHasNormalScan[INDEX_MAX_KEYS] = {false};
                                270                 :                :     MemoryContext oldCtx;
                                271                 :                : 
                                272                 :                :     /*
                                273                 :                :      * Allocate all the scan key information in the key context. (If
                                274                 :                :      * extractQuery leaks anything there, it won't be reset until the end of
                                275                 :                :      * scan or rescan, but that's OK.)
                                276                 :                :      */
 3357 heikki.linnakangas@i      277                 :            799 :     oldCtx = MemoryContextSwitchTo(so->keyCtx);
                                278                 :                : 
                                279                 :                :     /* if no scan keys provided, allocate extra EVERYTHING GinScanKey */
 4846 tgl@sss.pgh.pa.us         280                 :            799 :     so->keys = (GinScanKey)
                                281                 :            799 :         palloc(Max(scan->numberOfKeys, 1) * sizeof(GinScanKeyData));
 4845                           282                 :            799 :     so->nkeys = 0;
                                283                 :                : 
                                284                 :                :     /* initialize expansible array of GinScanEntry pointers */
                                285                 :            799 :     so->totalentries = 0;
                                286                 :            799 :     so->allocentries = 32;
                                287                 :            799 :     so->entries = (GinScanEntry *)
 2954                           288                 :            799 :         palloc(so->allocentries * sizeof(GinScanEntry));
                                289                 :                : 
 6283 teodor@sigaev.ru          290                 :            799 :     so->isVoidRes = false;
                                291                 :                : 
 6402 bruce@momjian.us          292         [ +  + ]:           1656 :     for (i = 0; i < scan->numberOfKeys; i++)
                                293                 :                :     {
 5499 tgl@sss.pgh.pa.us         294                 :            863 :         ScanKey     skey = &scankey[i];
                                295                 :                :         Datum      *queryValues;
 4846                           296                 :            863 :         int32       nQueryValues = 0;
 5421 bruce@momjian.us          297                 :            863 :         bool       *partial_matches = NULL;
                                298                 :            863 :         Pointer    *extra_data = NULL;
 4846 tgl@sss.pgh.pa.us         299                 :            863 :         bool       *nullFlags = NULL;
                                300                 :                :         GinNullCategory *categories;
                                301                 :            863 :         int32       searchMode = GIN_SEARCH_MODE_DEFAULT;
                                302                 :                : 
                                303                 :                :         /*
                                304                 :                :          * We assume that GIN-indexable operators are strict, so a null query
                                305                 :                :          * argument means an unsatisfiable query.
                                306                 :                :          */
 5499                           307         [ -  + ]:            863 :         if (skey->sk_flags & SK_ISNULL)
                                308                 :                :         {
 5488 teodor@sigaev.ru          309                 :UBC           0 :             so->isVoidRes = true;
                                310                 :              0 :             break;
                                311                 :                :         }
                                312                 :                : 
                                313                 :                :         /* OK to call the extractQueryFn */
                                314                 :                :         queryValues = (Datum *)
 4741 tgl@sss.pgh.pa.us         315                 :CBC        2589 :             DatumGetPointer(FunctionCall7Coll(&so->ginstate.extractQueryFn[skey->sk_attno - 1],
 2489                           316                 :            863 :                                               so->ginstate.supportCollation[skey->sk_attno - 1],
                                317                 :                :                                               skey->sk_argument,
                                318                 :                :                                               PointerGetDatum(&nQueryValues),
                                319                 :            863 :                                               UInt16GetDatum(skey->sk_strategy),
                                320                 :                :                                               PointerGetDatum(&partial_matches),
                                321                 :                :                                               PointerGetDatum(&extra_data),
                                322                 :                :                                               PointerGetDatum(&nullFlags),
                                323                 :                :                                               PointerGetDatum(&searchMode)));
                                324                 :                : 
                                325                 :                :         /*
                                326                 :                :          * If bogus searchMode is returned, treat as GIN_SEARCH_MODE_ALL; note
                                327                 :                :          * in particular we don't allow extractQueryFn to select
                                328                 :                :          * GIN_SEARCH_MODE_EVERYTHING.
                                329                 :                :          */
 4846                           330         [ +  - ]:            863 :         if (searchMode < GIN_SEARCH_MODE_DEFAULT ||
                                331         [ -  + ]:            863 :             searchMode > GIN_SEARCH_MODE_ALL)
 4846 tgl@sss.pgh.pa.us         332                 :UBC           0 :             searchMode = GIN_SEARCH_MODE_ALL;
                                333                 :                : 
                                334                 :                :         /* Non-default modes require the index to have placeholders */
 4846 tgl@sss.pgh.pa.us         335         [ +  + ]:CBC         863 :         if (searchMode != GIN_SEARCH_MODE_DEFAULT)
                                336                 :            182 :             hasNullQuery = true;
                                337                 :                : 
                                338                 :                :         /*
                                339                 :                :          * In default mode, no keys means an unsatisfiable query.
                                340                 :                :          */
                                341   [ +  +  +  + ]:            863 :         if (queryValues == NULL || nQueryValues <= 0)
                                342                 :                :         {
                                343         [ +  + ]:            152 :             if (searchMode == GIN_SEARCH_MODE_DEFAULT)
                                344                 :                :             {
                                345                 :              6 :                 so->isVoidRes = true;
                                346                 :              6 :                 break;
                                347                 :                :             }
                                348                 :            146 :             nQueryValues = 0;   /* ensure sane value */
                                349                 :                :         }
                                350                 :                : 
                                351                 :                :         /*
                                352                 :                :          * Create GinNullCategory representation.  If the extractQueryFn
                                353                 :                :          * didn't create a nullFlags array, we assume everything is non-null.
                                354                 :                :          * While at it, detect whether any null keys are present.
                                355                 :                :          */
 2301 peter_e@gmx.net           356                 :            857 :         categories = (GinNullCategory *) palloc0(nQueryValues * sizeof(GinNullCategory));
                                357         [ +  + ]:            857 :         if (nullFlags)
                                358                 :                :         {
                                359                 :                :             int32       j;
                                360                 :                : 
 4846 tgl@sss.pgh.pa.us         361         [ +  + ]:           2017 :             for (j = 0; j < nQueryValues; j++)
                                362                 :                :             {
                                363         [ -  + ]:           1732 :                 if (nullFlags[j])
                                364                 :                :                 {
 2301 peter_e@gmx.net           365                 :UBC           0 :                     categories[j] = GIN_CAT_NULL_KEY;
 4846 tgl@sss.pgh.pa.us         366                 :              0 :                     hasNullQuery = true;
                                367                 :                :                 }
                                368                 :                :             }
                                369                 :                :         }
                                370                 :                : 
 4845 tgl@sss.pgh.pa.us         371                 :CBC         857 :         ginFillScanKey(so, skey->sk_attno,
                                372                 :            857 :                        skey->sk_strategy, searchMode,
                                373                 :                :                        skey->sk_argument, nQueryValues,
                                374                 :                :                        queryValues, categories,
                                375                 :                :                        partial_matches, extra_data);
                                376                 :                : 
                                377                 :                :         /* Remember if we had any non-excludeOnly keys */
 1548 akorotkov@postgresql      378         [ +  + ]:            857 :         if (searchMode != GIN_SEARCH_MODE_ALL)
                                379                 :            697 :             attrHasNormalScan[skey->sk_attno - 1] = true;
                                380                 :                :     }
                                381                 :                : 
                                382                 :                :     /*
                                383                 :                :      * Processing GIN_SEARCH_MODE_ALL scan keys requires us to make a second
                                384                 :                :      * pass over the scan keys.  Above we marked each such scan key as
                                385                 :                :      * excludeOnly.  If the involved column has any normal (not excludeOnly)
                                386                 :                :      * scan key as well, then we can leave it like that.  Otherwise, one
                                387                 :                :      * excludeOnly scan key must receive a GIN_CAT_EMPTY_QUERY hidden entry
                                388                 :                :      * and be set to normal (excludeOnly = false).
                                389                 :                :      */
                                390         [ +  + ]:           1656 :     for (i = 0; i < so->nkeys; i++)
                                391                 :                :     {
                                392                 :            857 :         GinScanKey  key = &so->keys[i];
                                393                 :                : 
                                394         [ +  + ]:            857 :         if (key->searchMode != GIN_SEARCH_MODE_ALL)
                                395                 :            697 :             continue;
                                396                 :                : 
                                397         [ +  + ]:            160 :         if (!attrHasNormalScan[key->attnum - 1])
                                398                 :                :         {
                                399                 :            141 :             key->excludeOnly = false;
                                400                 :            141 :             ginScanKeyAddHiddenEntry(so, key, GIN_CAT_EMPTY_QUERY);
                                401                 :            141 :             attrHasNormalScan[key->attnum - 1] = true;
                                402                 :                :         }
                                403                 :                :     }
                                404                 :                : 
                                405                 :                :     /*
                                406                 :                :      * If there are no regular scan keys, generate an EVERYTHING scankey to
                                407                 :                :      * drive a full-index scan.
                                408                 :                :      */
 4845 tgl@sss.pgh.pa.us         409   [ +  +  -  + ]:            799 :     if (so->nkeys == 0 && !so->isVoidRes)
                                410                 :                :     {
 4846 tgl@sss.pgh.pa.us         411                 :UBC           0 :         hasNullQuery = true;
 4845                           412                 :              0 :         ginFillScanKey(so, FirstOffsetNumber,
                                413                 :                :                        InvalidStrategy, GIN_SEARCH_MODE_EVERYTHING,
                                414                 :                :                        (Datum) 0, 0,
                                415                 :                :                        NULL, NULL, NULL, NULL);
                                416                 :                :     }
                                417                 :                : 
                                418                 :                :     /*
                                419                 :                :      * If the index is version 0, it may be missing null and placeholder
                                420                 :                :      * entries, which would render searches for nulls and full-index scans
                                421                 :                :      * unreliable.  Throw an error if so.
                                422                 :                :      */
 4846 tgl@sss.pgh.pa.us         423   [ +  +  +  - ]:CBC         799 :     if (hasNullQuery && !so->isVoidRes)
                                424                 :                :     {
                                425                 :                :         GinStatsData ginStats;
                                426                 :                : 
                                427                 :            162 :         ginGetStats(scan->indexRelation, &ginStats);
                                428         [ -  + ]:            162 :         if (ginStats.ginVersion < 1)
 4846 tgl@sss.pgh.pa.us         429         [ #  # ]:UBC           0 :             ereport(ERROR,
                                430                 :                :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                431                 :                :                      errmsg("old GIN indexes do not support whole-index scans nor searches for nulls"),
                                432                 :                :                      errhint("To fix this, do REINDEX INDEX \"%s\".",
                                433                 :                :                              RelationGetRelationName(scan->indexRelation))));
                                434                 :                :     }
                                435                 :                : 
 3357 heikki.linnakangas@i      436                 :CBC         799 :     MemoryContextSwitchTo(oldCtx);
                                437                 :                : 
 6167 tgl@sss.pgh.pa.us         438   [ -  +  -  -  :            799 :     pgstat_count_index_scan(scan->indexRelation);
                                              +  - ]
 6557 teodor@sigaev.ru          439                 :            799 : }
                                440                 :                : 
                                441                 :                : void
 3010 tgl@sss.pgh.pa.us         442                 :            799 : ginrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys,
                                443                 :                :           ScanKey orderbys, int norderbys)
                                444                 :                : {
 4882                           445                 :            799 :     GinScanOpaque so = (GinScanOpaque) scan->opaque;
                                446                 :                : 
 3362 heikki.linnakangas@i      447                 :            799 :     ginFreeScanKeys(so);
                                448                 :                : 
 6402 bruce@momjian.us          449   [ +  -  +  - ]:            799 :     if (scankey && scan->numberOfKeys > 0)
                                450                 :                :     {
 6557 teodor@sigaev.ru          451                 :            799 :         memmove(scan->keyData, scankey,
 6402 bruce@momjian.us          452                 :            799 :                 scan->numberOfKeys * sizeof(ScanKeyData));
                                453                 :                :     }
 6557 teodor@sigaev.ru          454                 :            799 : }
                                455                 :                : 
                                456                 :                : 
                                457                 :                : void
 3010 tgl@sss.pgh.pa.us         458                 :            796 : ginendscan(IndexScanDesc scan)
                                459                 :                : {
 6402 bruce@momjian.us          460                 :            796 :     GinScanOpaque so = (GinScanOpaque) scan->opaque;
                                461                 :                : 
 3362 heikki.linnakangas@i      462                 :            796 :     ginFreeScanKeys(so);
                                463                 :                : 
 4882 tgl@sss.pgh.pa.us         464                 :            796 :     MemoryContextDelete(so->tempCtx);
 3357 heikki.linnakangas@i      465                 :            796 :     MemoryContextDelete(so->keyCtx);
                                466                 :                : 
 4882 tgl@sss.pgh.pa.us         467                 :            796 :     pfree(so);
 6557 teodor@sigaev.ru          468                 :            796 : }
        

Generated by: LCOV version 2.1-beta2-3-g6141622