PostgreSQL Source Code git master
ginscan.c File Reference
#include "postgres.h"
#include "access/gin_private.h"
#include "access/relscan.h"
#include "executor/instrument_node.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 26 of file ginscan.c.

27{
28 IndexScanDesc scan;
30
31 /* no order by operators allowed */
32 Assert(norderbys == 0);
33
34 scan = RelationGetIndexScan(rel, nkeys, norderbys);
35
36 /* allocate private workspace */
38 so->keys = NULL;
39 so->nkeys = 0;
41 "Gin scan temporary context",
44 "Gin scan key context",
47
48 scan->opaque = so;
49
50 return scan;
51}
#define palloc_object(type)
Definition: fe_memutils.h:74
IndexScanDesc RelationGetIndexScan(Relation indexRelation, int nkeys, int norderbys)
Definition: genam.c:80
GinScanOpaqueData * GinScanOpaque
Definition: gin_private.h:389
void initGinState(GinState *state, Relation index)
Definition: ginutil.c:103
Assert(PointerIsAligned(start, uint64))
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:377
MemoryContext keyCtx
Definition: gin_private.h:384
MemoryContext tempCtx
Definition: gin_private.h:374
Relation indexRelation
Definition: relscan.h:138

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

Referenced by ginhandler().

◆ ginendscan()

void ginendscan ( IndexScanDesc  scan)

Definition at line 504 of file ginscan.c.

505{
507
508 ginFreeScanKeys(so);
509
512
513 pfree(so);
514}
void ginFreeScanKeys(GinScanOpaque so)
Definition: ginscan.c:237
void pfree(void *pointer)
Definition: mcxt.c:1616
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:472

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 58 of file ginscan.c.

62{
63 GinState *ginstate = &so->ginstate;
64 GinScanEntry scanEntry;
65 uint32 i;
66
67 /*
68 * Look for an existing equivalent entry.
69 *
70 * Entries with non-null extra_data are never considered identical, since
71 * we can't know exactly what the opclass might be doing with that.
72 *
73 * Also, give up de-duplication once we have 100 entries. That avoids
74 * spending O(N^2) time on probably-fruitless de-duplication of large
75 * search-key sets. The threshold of 100 is arbitrary but matches
76 * predtest.c's threshold for what's a large array.
77 */
78 if (extra_data == NULL && so->totalentries < 100)
79 {
80 for (i = 0; i < so->totalentries; i++)
81 {
82 GinScanEntry prevEntry = so->entries[i];
83
84 if (prevEntry->extra_data == NULL &&
85 prevEntry->isPartialMatch == isPartialMatch &&
86 prevEntry->strategy == strategy &&
87 prevEntry->searchMode == searchMode &&
88 prevEntry->attnum == attnum &&
89 ginCompareEntries(ginstate, attnum,
90 prevEntry->queryKey,
91 prevEntry->queryCategory,
92 queryKey,
93 queryCategory) == 0)
94 {
95 /* Successful match */
96 return prevEntry;
97 }
98 }
99 }
100
101 /* Nope, create a new entry */
102 scanEntry = palloc_object(GinScanEntryData);
103 scanEntry->queryKey = queryKey;
104 scanEntry->queryCategory = queryCategory;
105 scanEntry->isPartialMatch = isPartialMatch;
106 scanEntry->extra_data = extra_data;
107 scanEntry->strategy = strategy;
108 scanEntry->searchMode = searchMode;
109 scanEntry->attnum = attnum;
110
111 scanEntry->buffer = InvalidBuffer;
112 ItemPointerSetMin(&scanEntry->curItem);
113 scanEntry->matchBitmap = NULL;
114 scanEntry->matchIterator = NULL;
116 scanEntry->matchNtuples = -1;
117 scanEntry->list = NULL;
118 scanEntry->nlist = 0;
119 scanEntry->offset = InvalidOffsetNumber;
120 scanEntry->isFinished = false;
121 scanEntry->reduceResult = false;
122
123 /* Add it to so's array */
124 if (so->totalentries >= so->allocentries)
125 {
126 so->allocentries *= 2;
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:546
#define repalloc_array(pointer, type, count)
Definition: fe_memutils.h:78
static int ginCompareEntries(GinState *ginstate, OffsetNumber attnum, Datum a, GinNullCategory categorya, Datum b, GinNullCategory categoryb)
Definition: gin_private.h:503
#define ItemPointerSetMin(p)
Definition: ginblock.h:166
int i
Definition: isn.c:77
#define InvalidOffsetNumber
Definition: off.h:26
int16 attnum
Definition: pg_attribute.h:74
ItemPointerData curItem
Definition: gin_private.h:347
TBMIterateResult matchResult
Definition: gin_private.h:357
TIDBitmap * matchBitmap
Definition: gin_private.h:350
ItemPointerData * list
Definition: gin_private.h:362
TBMPrivateIterator * matchIterator
Definition: gin_private.h:351
GinNullCategory queryCategory
Definition: gin_private.h:336
StrategyNumber strategy
Definition: gin_private.h:339
Pointer extra_data
Definition: gin_private.h:338
OffsetNumber offset
Definition: gin_private.h:364
OffsetNumber attnum
Definition: gin_private.h:341
GinScanEntry * entries
Definition: gin_private.h:380
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_object, GinScanEntryData::queryCategory, GinScanEntryData::queryKey, GinScanEntryData::reduceResult, repalloc_array, 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 = palloc_array(GinScanEntry, nQueryValues + 1);
174 key->entryRes = palloc0_array(GinTernaryValue, nQueryValues + 1);
175
176 key->query = query;
177 key->queryValues = queryValues;
178 key->queryCategories = queryCategories;
179 key->extra_data = extra_data;
180 key->strategy = strategy;
181 key->searchMode = searchMode;
182 key->attnum = attnum;
183
184 /*
185 * Initially, scan keys of GIN_SEARCH_MODE_ALL mode are marked
186 * excludeOnly. This might get changed later.
187 */
188 key->excludeOnly = (searchMode == GIN_SEARCH_MODE_ALL);
189
190 ItemPointerSetMin(&key->curItem);
191 key->curItemMatches = false;
192 key->recheckCurItem = false;
193 key->isFinished = false;
194 key->nrequired = 0;
195 key->nadditional = 0;
196 key->requiredEntries = NULL;
197 key->additionalEntries = NULL;
198
200
201 /* Set up normal scan entries using extractQueryFn's outputs */
202 for (i = 0; i < nQueryValues; i++)
203 {
204 Datum queryKey;
205 GinNullCategory queryCategory;
206 bool isPartialMatch;
207 Pointer this_extra;
208
209 queryKey = queryValues[i];
210 queryCategory = queryCategories[i];
211 isPartialMatch =
212 (ginstate->canPartialMatch[attnum - 1] && partial_matches)
213 ? partial_matches[i] : false;
214 this_extra = (extra_data) ? extra_data[i] : NULL;
215
216 key->scanEntry[i] = ginFillScanEntry(so, attnum,
217 strategy, searchMode,
218 queryKey, queryCategory,
219 isPartialMatch, this_extra);
220 }
221
222 /*
223 * For GIN_SEARCH_MODE_INCLUDE_EMPTY and GIN_SEARCH_MODE_EVERYTHING search
224 * modes, we add the "hidden" entry immediately. GIN_SEARCH_MODE_ALL is
225 * handled later, since we might be able to omit the hidden entry for it.
226 */
227 if (searchMode == GIN_SEARCH_MODE_INCLUDE_EMPTY)
229 else if (searchMode == GIN_SEARCH_MODE_EVERYTHING)
231}
void * Pointer
Definition: c.h:537
#define palloc_array(type, count)
Definition: fe_memutils.h:76
#define palloc0_array(type, count)
Definition: fe_memutils.h:77
#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:58
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, palloc0_array, and palloc_array.

◆ ginFreeScanKeys()

void ginFreeScanKeys ( GinScanOpaque  so)

Definition at line 237 of file ginscan.c.

238{
239 uint32 i;
240
241 if (so->keys == NULL)
242 return;
243
244 for (i = 0; i < so->totalentries; i++)
245 {
246 GinScanEntry entry = so->entries[i];
247
248 if (entry->buffer != InvalidBuffer)
249 ReleaseBuffer(entry->buffer);
250 if (entry->list)
251 pfree(entry->list);
252 if (entry->matchIterator)
254 if (entry->matchBitmap)
255 tbm_free(entry->matchBitmap);
256 }
257
259
260 so->keys = NULL;
261 so->nkeys = 0;
262 so->entries = NULL;
263 so->totalentries = 0;
264}
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:5501
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:403
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 267 of file ginscan.c.

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

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

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().