PostgreSQL Source Code git master
ginscan.c File Reference
#include "postgres.h"
#include "access/gin_private.h"
#include "access/relscan.h"
#include "pgstat.h"
#include "utils/memutils.h"
#include "utils/rel.h"
Include dependency graph for ginscan.c:

Go to the source code of this file.

Functions

IndexScanDesc ginbeginscan (Relation rel, int nkeys, int norderbys)
 
static GinScanEntry ginFillScanEntry (GinScanOpaque so, OffsetNumber attnum, StrategyNumber strategy, int32 searchMode, Datum queryKey, GinNullCategory queryCategory, bool isPartialMatch, Pointer extra_data)
 
static void ginScanKeyAddHiddenEntry (GinScanOpaque so, GinScanKey key, GinNullCategory queryCategory)
 
static void ginFillScanKey (GinScanOpaque so, OffsetNumber attnum, StrategyNumber strategy, int32 searchMode, Datum query, uint32 nQueryValues, Datum *queryValues, GinNullCategory *queryCategories, bool *partial_matches, Pointer *extra_data)
 
void ginFreeScanKeys (GinScanOpaque so)
 
void ginNewScanKey (IndexScanDesc scan)
 
void ginrescan (IndexScanDesc scan, ScanKey scankey, int nscankeys, ScanKey orderbys, int norderbys)
 
void ginendscan (IndexScanDesc scan)
 

Function Documentation

◆ ginbeginscan()

IndexScanDesc ginbeginscan ( Relation  rel,
int  nkeys,
int  norderbys 
)

Definition at line 25 of file ginscan.c.

26{
27 IndexScanDesc scan;
29
30 /* no order by operators allowed */
31 Assert(norderbys == 0);
32
33 scan = RelationGetIndexScan(rel, nkeys, norderbys);
34
35 /* allocate private workspace */
37 so->keys = NULL;
38 so->nkeys = 0;
40 "Gin scan temporary context",
43 "Gin scan key context",
46
47 scan->opaque = so;
48
49 return scan;
50}
IndexScanDesc RelationGetIndexScan(Relation indexRelation, int nkeys, int norderbys)
Definition: genam.c:80
GinScanOpaqueData * GinScanOpaque
Definition: gin_private.h:395
void initGinState(GinState *state, Relation index)
Definition: ginutil.c:102
Assert(PointerIsAligned(start, uint64))
void * palloc(Size size)
Definition: mcxt.c:1365
MemoryContext CurrentMemoryContext
Definition: mcxt.c:160
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
GinScanKey keys
Definition: gin_private.h:383
MemoryContext keyCtx
Definition: gin_private.h:390
MemoryContext tempCtx
Definition: gin_private.h:380
Relation indexRelation
Definition: relscan.h:139

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert(), CurrentMemoryContext, GinScanOpaqueData::ginstate, IndexScanDescData::indexRelation, initGinState(), GinScanOpaqueData::keyCtx, GinScanOpaqueData::keys, GinScanOpaqueData::nkeys, IndexScanDescData::opaque, palloc(), RelationGetIndexScan(), and GinScanOpaqueData::tempCtx.

Referenced by ginhandler().

◆ ginendscan()

void ginendscan ( IndexScanDesc  scan)

Definition at line 506 of file ginscan.c.

507{
509
510 ginFreeScanKeys(so);
511
514
515 pfree(so);
516}
void ginFreeScanKeys(GinScanOpaque so)
Definition: ginscan.c:239
void pfree(void *pointer)
Definition: mcxt.c:1594
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:469

References ginFreeScanKeys(), GinScanOpaqueData::keyCtx, MemoryContextDelete(), IndexScanDescData::opaque, pfree(), and GinScanOpaqueData::tempCtx.

Referenced by ginhandler().

◆ ginFillScanEntry()

static GinScanEntry ginFillScanEntry ( GinScanOpaque  so,
OffsetNumber  attnum,
StrategyNumber  strategy,
int32  searchMode,
Datum  queryKey,
GinNullCategory  queryCategory,
bool  isPartialMatch,
Pointer  extra_data 
)
static

Definition at line 57 of file ginscan.c.

61{
62 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 * Also, give up de-duplication once we have 100 entries. That avoids
73 * spending O(N^2) time on probably-fruitless de-duplication of large
74 * search-key sets. The threshold of 100 is arbitrary but matches
75 * predtest.c's threshold for what's a large array.
76 */
77 if (extra_data == NULL && so->totalentries < 100)
78 {
79 for (i = 0; i < so->totalentries; i++)
80 {
81 GinScanEntry prevEntry = so->entries[i];
82
83 if (prevEntry->extra_data == NULL &&
84 prevEntry->isPartialMatch == isPartialMatch &&
85 prevEntry->strategy == strategy &&
86 prevEntry->searchMode == searchMode &&
87 prevEntry->attnum == attnum &&
88 ginCompareEntries(ginstate, attnum,
89 prevEntry->queryKey,
90 prevEntry->queryCategory,
91 queryKey,
92 queryCategory) == 0)
93 {
94 /* Successful match */
95 return prevEntry;
96 }
97 }
98 }
99
100 /* Nope, create a new entry */
101 scanEntry = (GinScanEntry) palloc(sizeof(GinScanEntryData));
102 scanEntry->queryKey = queryKey;
103 scanEntry->queryCategory = queryCategory;
104 scanEntry->isPartialMatch = isPartialMatch;
105 scanEntry->extra_data = extra_data;
106 scanEntry->strategy = strategy;
107 scanEntry->searchMode = searchMode;
108 scanEntry->attnum = attnum;
109
110 scanEntry->buffer = InvalidBuffer;
111 ItemPointerSetMin(&scanEntry->curItem);
112 scanEntry->matchBitmap = NULL;
113 scanEntry->matchIterator = NULL;
115 scanEntry->matchNtuples = -1;
116 scanEntry->list = NULL;
117 scanEntry->nlist = 0;
118 scanEntry->offset = InvalidOffsetNumber;
119 scanEntry->isFinished = false;
120 scanEntry->reduceResult = false;
121
122 /* Add it to so's array */
123 if (so->totalentries >= so->allocentries)
124 {
125 so->allocentries *= 2;
126 so->entries = (GinScanEntry *)
127 repalloc(so->entries, so->allocentries * sizeof(GinScanEntry));
128 }
129 so->entries[so->totalentries++] = scanEntry;
130
131 return scanEntry;
132}
#define InvalidBlockNumber
Definition: block.h:33
#define InvalidBuffer
Definition: buf.h:25
uint32_t uint32
Definition: c.h:541
struct GinScanEntryData * GinScanEntry
Definition: gin_private.h:268
#define ItemPointerSetMin(p)
Definition: ginblock.h:166
int ginCompareEntries(GinState *ginstate, OffsetNumber attnum, Datum a, GinNullCategory categorya, Datum b, GinNullCategory categoryb)
Definition: ginutil.c:393
int i
Definition: isn.c:77
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1610
#define InvalidOffsetNumber
Definition: off.h:26
int16 attnum
Definition: pg_attribute.h:74
ItemPointerData curItem
Definition: gin_private.h:353
TBMIterateResult matchResult
Definition: gin_private.h:363
TIDBitmap * matchBitmap
Definition: gin_private.h:356
ItemPointerData * list
Definition: gin_private.h:368
TBMPrivateIterator * matchIterator
Definition: gin_private.h:357
GinNullCategory queryCategory
Definition: gin_private.h:342
StrategyNumber strategy
Definition: gin_private.h:345
Pointer extra_data
Definition: gin_private.h:344
OffsetNumber offset
Definition: gin_private.h:370
OffsetNumber attnum
Definition: gin_private.h:347
GinScanEntry * entries
Definition: gin_private.h:386
BlockNumber blockno
Definition: tidbitmap.h:63

References GinScanOpaqueData::allocentries, GinScanEntryData::attnum, attnum, TBMIterateResult::blockno, GinScanEntryData::buffer, GinScanEntryData::curItem, GinScanOpaqueData::entries, GinScanEntryData::extra_data, ginCompareEntries(), GinScanOpaqueData::ginstate, i, InvalidBlockNumber, InvalidBuffer, InvalidOffsetNumber, GinScanEntryData::isFinished, GinScanEntryData::isPartialMatch, ItemPointerSetMin, GinScanEntryData::list, GinScanEntryData::matchBitmap, GinScanEntryData::matchIterator, GinScanEntryData::matchNtuples, GinScanEntryData::matchResult, GinScanEntryData::nlist, GinScanEntryData::offset, palloc(), GinScanEntryData::queryCategory, GinScanEntryData::queryKey, GinScanEntryData::reduceResult, repalloc(), GinScanEntryData::searchMode, GinScanEntryData::strategy, and GinScanOpaqueData::totalentries.

Referenced by ginFillScanKey(), and ginScanKeyAddHiddenEntry().

◆ ginFillScanKey()

static void ginFillScanKey ( GinScanOpaque  so,
OffsetNumber  attnum,
StrategyNumber  strategy,
int32  searchMode,
Datum  query,
uint32  nQueryValues,
Datum queryValues,
GinNullCategory queryCategories,
bool *  partial_matches,
Pointer extra_data 
)
static

Definition at line 159 of file ginscan.c.

164{
165 GinScanKey key = &(so->keys[so->nkeys++]);
166 GinState *ginstate = &so->ginstate;
167 uint32 i;
168
169 key->nentries = nQueryValues;
170 key->nuserentries = nQueryValues;
171
172 /* Allocate one extra array slot for possible "hidden" entry */
173 key->scanEntry = (GinScanEntry *) palloc(sizeof(GinScanEntry) *
174 (nQueryValues + 1));
175 key->entryRes = (GinTernaryValue *) palloc0(sizeof(GinTernaryValue) *
176 (nQueryValues + 1));
177
178 key->query = query;
179 key->queryValues = queryValues;
180 key->queryCategories = queryCategories;
181 key->extra_data = extra_data;
182 key->strategy = strategy;
183 key->searchMode = searchMode;
184 key->attnum = attnum;
185
186 /*
187 * Initially, scan keys of GIN_SEARCH_MODE_ALL mode are marked
188 * excludeOnly. This might get changed later.
189 */
190 key->excludeOnly = (searchMode == GIN_SEARCH_MODE_ALL);
191
192 ItemPointerSetMin(&key->curItem);
193 key->curItemMatches = false;
194 key->recheckCurItem = false;
195 key->isFinished = false;
196 key->nrequired = 0;
197 key->nadditional = 0;
198 key->requiredEntries = NULL;
199 key->additionalEntries = NULL;
200
202
203 /* Set up normal scan entries using extractQueryFn's outputs */
204 for (i = 0; i < nQueryValues; i++)
205 {
206 Datum queryKey;
207 GinNullCategory queryCategory;
208 bool isPartialMatch;
209 Pointer this_extra;
210
211 queryKey = queryValues[i];
212 queryCategory = queryCategories[i];
213 isPartialMatch =
214 (ginstate->canPartialMatch[attnum - 1] && partial_matches)
215 ? partial_matches[i] : false;
216 this_extra = (extra_data) ? extra_data[i] : NULL;
217
218 key->scanEntry[i] = ginFillScanEntry(so, attnum,
219 strategy, searchMode,
220 queryKey, queryCategory,
221 isPartialMatch, this_extra);
222 }
223
224 /*
225 * For GIN_SEARCH_MODE_INCLUDE_EMPTY and GIN_SEARCH_MODE_EVERYTHING search
226 * modes, we add the "hidden" entry immediately. GIN_SEARCH_MODE_ALL is
227 * handled later, since we might be able to omit the hidden entry for it.
228 */
229 if (searchMode == GIN_SEARCH_MODE_INCLUDE_EMPTY)
231 else if (searchMode == GIN_SEARCH_MODE_EVERYTHING)
233}
void * Pointer
Definition: c.h:532
#define GIN_SEARCH_MODE_ALL
Definition: gin.h:38
#define GIN_SEARCH_MODE_EVERYTHING
Definition: gin.h:39
char GinTernaryValue
Definition: gin.h:71
#define GIN_SEARCH_MODE_INCLUDE_EMPTY
Definition: gin.h:37
#define GIN_CAT_EMPTY_ITEM
Definition: ginblock.h:210
signed char GinNullCategory
Definition: ginblock.h:206
#define GIN_CAT_EMPTY_QUERY
Definition: ginblock.h:212
void ginInitConsistentFunction(GinState *ginstate, GinScanKey key)
Definition: ginlogic.c:227
static void ginScanKeyAddHiddenEntry(GinScanOpaque so, GinScanKey key, GinNullCategory queryCategory)
Definition: ginscan.c:143
static GinScanEntry ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum, StrategyNumber strategy, int32 searchMode, Datum queryKey, GinNullCategory queryCategory, bool isPartialMatch, Pointer extra_data)
Definition: ginscan.c:57
void * palloc0(Size size)
Definition: mcxt.c:1395
uint64_t Datum
Definition: postgres.h:70
bool canPartialMatch[INDEX_MAX_KEYS]
Definition: gin_private.h:87

References attnum, GinState::canPartialMatch, GIN_CAT_EMPTY_ITEM, GIN_CAT_EMPTY_QUERY, GIN_SEARCH_MODE_ALL, GIN_SEARCH_MODE_EVERYTHING, GIN_SEARCH_MODE_INCLUDE_EMPTY, ginFillScanEntry(), ginInitConsistentFunction(), ginScanKeyAddHiddenEntry(), GinScanOpaqueData::ginstate, i, ItemPointerSetMin, sort-test::key, GinScanOpaqueData::keys, GinScanOpaqueData::nkeys, palloc(), and palloc0().

◆ ginFreeScanKeys()

void ginFreeScanKeys ( GinScanOpaque  so)

Definition at line 239 of file ginscan.c.

240{
241 uint32 i;
242
243 if (so->keys == NULL)
244 return;
245
246 for (i = 0; i < so->totalentries; i++)
247 {
248 GinScanEntry entry = so->entries[i];
249
250 if (entry->buffer != InvalidBuffer)
251 ReleaseBuffer(entry->buffer);
252 if (entry->list)
253 pfree(entry->list);
254 if (entry->matchIterator)
256 if (entry->matchBitmap)
257 tbm_free(entry->matchBitmap);
258 }
259
261
262 so->keys = NULL;
263 so->nkeys = 0;
264 so->entries = NULL;
265 so->totalentries = 0;
266}
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:5366
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:400
void tbm_free(TIDBitmap *tbm)
Definition: tidbitmap.c:312
void tbm_end_private_iterate(TBMPrivateIterator *iterator)
Definition: tidbitmap.c:1147

References GinScanEntryData::buffer, GinScanOpaqueData::entries, i, InvalidBuffer, GinScanOpaqueData::keyCtx, GinScanOpaqueData::keys, GinScanEntryData::list, GinScanEntryData::matchBitmap, GinScanEntryData::matchIterator, MemoryContextReset(), GinScanOpaqueData::nkeys, pfree(), ReleaseBuffer(), tbm_end_private_iterate(), tbm_free(), and GinScanOpaqueData::totalentries.

Referenced by ginendscan(), gingetbitmap(), and ginrescan().

◆ ginNewScanKey()

void ginNewScanKey ( IndexScanDesc  scan)

Definition at line 269 of file ginscan.c.

270{
271 ScanKey scankey = scan->keyData;
273 int i;
274 int numExcludeOnly;
275 bool hasNullQuery = false;
276 bool attrHasNormalScan[INDEX_MAX_KEYS] = {false};
277 MemoryContext oldCtx;
278
279 /*
280 * Allocate all the scan key information in the key context. (If
281 * extractQuery leaks anything there, it won't be reset until the end of
282 * scan or rescan, but that's OK.)
283 */
284 oldCtx = MemoryContextSwitchTo(so->keyCtx);
285
286 /* if no scan keys provided, allocate extra EVERYTHING GinScanKey */
287 so->keys = (GinScanKey)
288 palloc(Max(scan->numberOfKeys, 1) * sizeof(GinScanKeyData));
289 so->nkeys = 0;
290
291 /* initialize expansible array of GinScanEntry pointers */
292 so->totalentries = 0;
293 so->allocentries = 32;
294 so->entries = (GinScanEntry *)
295 palloc(so->allocentries * sizeof(GinScanEntry));
296
297 so->isVoidRes = false;
298
299 for (i = 0; i < scan->numberOfKeys; i++)
300 {
301 ScanKey skey = &scankey[i];
302 Datum *queryValues;
303 int32 nQueryValues = 0;
304 bool *partial_matches = NULL;
305 Pointer *extra_data = NULL;
306 bool *nullFlags = NULL;
307 GinNullCategory *categories;
308 int32 searchMode = GIN_SEARCH_MODE_DEFAULT;
309
310 /*
311 * We assume that GIN-indexable operators are strict, so a null query
312 * argument means an unsatisfiable query.
313 */
314 if (skey->sk_flags & SK_ISNULL)
315 {
316 so->isVoidRes = true;
317 break;
318 }
319
320 /* OK to call the extractQueryFn */
321 queryValues = (Datum *)
322 DatumGetPointer(FunctionCall7Coll(&so->ginstate.extractQueryFn[skey->sk_attno - 1],
323 so->ginstate.supportCollation[skey->sk_attno - 1],
324 skey->sk_argument,
325 PointerGetDatum(&nQueryValues),
327 PointerGetDatum(&partial_matches),
328 PointerGetDatum(&extra_data),
329 PointerGetDatum(&nullFlags),
330 PointerGetDatum(&searchMode)));
331
332 /*
333 * If bogus searchMode is returned, treat as GIN_SEARCH_MODE_ALL; note
334 * in particular we don't allow extractQueryFn to select
335 * GIN_SEARCH_MODE_EVERYTHING.
336 */
337 if (searchMode < GIN_SEARCH_MODE_DEFAULT ||
338 searchMode > GIN_SEARCH_MODE_ALL)
339 searchMode = GIN_SEARCH_MODE_ALL;
340
341 /* Non-default modes require the index to have placeholders */
342 if (searchMode != GIN_SEARCH_MODE_DEFAULT)
343 hasNullQuery = true;
344
345 /*
346 * In default mode, no keys means an unsatisfiable query.
347 */
348 if (queryValues == NULL || nQueryValues <= 0)
349 {
350 if (searchMode == GIN_SEARCH_MODE_DEFAULT)
351 {
352 so->isVoidRes = true;
353 break;
354 }
355 nQueryValues = 0; /* ensure sane value */
356 }
357
358 /*
359 * Create GinNullCategory representation. If the extractQueryFn
360 * didn't create a nullFlags array, we assume everything is non-null.
361 * While at it, detect whether any null keys are present.
362 */
363 categories = (GinNullCategory *) palloc0(nQueryValues * sizeof(GinNullCategory));
364 if (nullFlags)
365 {
366 int32 j;
367
368 for (j = 0; j < nQueryValues; j++)
369 {
370 if (nullFlags[j])
371 {
372 categories[j] = GIN_CAT_NULL_KEY;
373 hasNullQuery = true;
374 }
375 }
376 }
377
378 ginFillScanKey(so, skey->sk_attno,
379 skey->sk_strategy, searchMode,
380 skey->sk_argument, nQueryValues,
381 queryValues, categories,
382 partial_matches, extra_data);
383
384 /* Remember if we had any non-excludeOnly keys */
385 if (searchMode != GIN_SEARCH_MODE_ALL)
386 attrHasNormalScan[skey->sk_attno - 1] = true;
387 }
388
389 /*
390 * Processing GIN_SEARCH_MODE_ALL scan keys requires us to make a second
391 * pass over the scan keys. Above we marked each such scan key as
392 * excludeOnly. If the involved column has any normal (not excludeOnly)
393 * scan key as well, then we can leave it like that. Otherwise, one
394 * excludeOnly scan key must receive a GIN_CAT_EMPTY_QUERY hidden entry
395 * and be set to normal (excludeOnly = false).
396 */
397 numExcludeOnly = 0;
398 for (i = 0; i < so->nkeys; i++)
399 {
400 GinScanKey key = &so->keys[i];
401
402 if (key->searchMode != GIN_SEARCH_MODE_ALL)
403 continue;
404
405 if (!attrHasNormalScan[key->attnum - 1])
406 {
407 key->excludeOnly = false;
409 attrHasNormalScan[key->attnum - 1] = true;
410 }
411 else
412 numExcludeOnly++;
413 }
414
415 /*
416 * If we left any excludeOnly scan keys as-is, move them to the end of the
417 * scan key array: they must appear after normal key(s).
418 */
419 if (numExcludeOnly > 0)
420 {
421 GinScanKey tmpkeys;
422 int iNormalKey;
423 int iExcludeOnly;
424
425 /* We'd better have made at least one normal key */
426 Assert(numExcludeOnly < so->nkeys);
427 /* Make a temporary array to hold the re-ordered scan keys */
428 tmpkeys = (GinScanKey) palloc(so->nkeys * sizeof(GinScanKeyData));
429 /* Re-order the keys ... */
430 iNormalKey = 0;
431 iExcludeOnly = so->nkeys - numExcludeOnly;
432 for (i = 0; i < so->nkeys; i++)
433 {
434 GinScanKey key = &so->keys[i];
435
436 if (key->excludeOnly)
437 {
438 memcpy(tmpkeys + iExcludeOnly, key, sizeof(GinScanKeyData));
439 iExcludeOnly++;
440 }
441 else
442 {
443 memcpy(tmpkeys + iNormalKey, key, sizeof(GinScanKeyData));
444 iNormalKey++;
445 }
446 }
447 Assert(iNormalKey == so->nkeys - numExcludeOnly);
448 Assert(iExcludeOnly == so->nkeys);
449 /* ... and copy them back to so->keys[] */
450 memcpy(so->keys, tmpkeys, so->nkeys * sizeof(GinScanKeyData));
451 pfree(tmpkeys);
452 }
453
454 /*
455 * If there are no regular scan keys, generate an EVERYTHING scankey to
456 * drive a full-index scan.
457 */
458 if (so->nkeys == 0 && !so->isVoidRes)
459 {
460 hasNullQuery = true;
463 (Datum) 0, 0,
464 NULL, NULL, NULL, NULL);
465 }
466
467 /*
468 * If the index is version 0, it may be missing null and placeholder
469 * entries, which would render searches for nulls and full-index scans
470 * unreliable. Throw an error if so.
471 */
472 if (hasNullQuery && !so->isVoidRes)
473 {
474 GinStatsData ginStats;
475
476 ginGetStats(scan->indexRelation, &ginStats);
477 if (ginStats.ginVersion < 1)
479 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
480 errmsg("old GIN indexes do not support whole-index scans nor searches for nulls"),
481 errhint("To fix this, do REINDEX INDEX \"%s\".",
483 }
484
485 MemoryContextSwitchTo(oldCtx);
486
488 if (scan->instrument)
489 scan->instrument->nsearches++;
490}
#define Max(x, y)
Definition: c.h:1000
int32_t int32
Definition: c.h:537
int errhint(const char *fmt,...)
Definition: elog.c:1330
int errcode(int sqlerrcode)
Definition: elog.c:863
int errmsg(const char *fmt,...)
Definition: elog.c:1080
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:150
Datum FunctionCall7Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5, Datum arg6, Datum arg7)
Definition: fmgr.c:1285
#define GIN_SEARCH_MODE_DEFAULT
Definition: gin.h:36
struct GinScanKeyData GinScanKeyData
struct GinScanKeyData * GinScanKey
Definition: gin_private.h:266
#define GIN_CAT_NULL_KEY
Definition: ginblock.h:209
static void ginFillScanKey(GinScanOpaque so, OffsetNumber attnum, StrategyNumber strategy, int32 searchMode, Datum query, uint32 nQueryValues, Datum *queryValues, GinNullCategory *queryCategories, bool *partial_matches, Pointer *extra_data)
Definition: ginscan.c:159
void ginGetStats(Relation index, GinStatsData *stats)
Definition: ginutil.c:628
int j
Definition: isn.c:78
#define FirstOffsetNumber
Definition: off.h:27
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
#define INDEX_MAX_KEYS
#define pgstat_count_index_scan(rel)
Definition: pgstat.h:705
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:332
static Datum UInt16GetDatum(uint16 X)
Definition: postgres.h:202
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:322
#define RelationGetRelationName(relation)
Definition: rel.h:549
#define SK_ISNULL
Definition: skey.h:115
#define InvalidStrategy
Definition: stratnum.h:24
int32 ginVersion
Definition: gin.h:62
struct ScanKeyData * keyData
Definition: relscan.h:143
struct IndexScanInstrumentation * instrument
Definition: relscan.h:161
int sk_flags
Definition: skey.h:66
Datum sk_argument
Definition: skey.h:72
StrategyNumber sk_strategy
Definition: skey.h:68
AttrNumber sk_attno
Definition: skey.h:67

References i, INDEX_MAX_KEYS, IndexScanDescData::keyData, and IndexScanDescData::opaque.

Referenced by gingetbitmap().

◆ ginrescan()

void ginrescan ( IndexScanDesc  scan,
ScanKey  scankey,
int  nscankeys,
ScanKey  orderbys,
int  norderbys 
)

Definition at line 493 of file ginscan.c.

495{
497
498 ginFreeScanKeys(so);
499
500 if (scankey && scan->numberOfKeys > 0)
501 memcpy(scan->keyData, scankey, scan->numberOfKeys * sizeof(ScanKeyData));
502}

References ginFreeScanKeys(), IndexScanDescData::keyData, IndexScanDescData::numberOfKeys, and IndexScanDescData::opaque.

Referenced by ginhandler().

◆ ginScanKeyAddHiddenEntry()

static void ginScanKeyAddHiddenEntry ( GinScanOpaque  so,
GinScanKey  key,
GinNullCategory  queryCategory 
)
static

Definition at line 143 of file ginscan.c.

145{
146 int i = key->nentries++;
147
148 /* strategy is of no interest because this is not a partial-match item */
149 key->scanEntry[i] = ginFillScanEntry(so, key->attnum,
150 InvalidStrategy, key->searchMode,
151 (Datum) 0, queryCategory,
152 false, NULL);
153}

References ginFillScanEntry(), i, InvalidStrategy, and sort-test::key.

Referenced by ginFillScanKey().