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}
#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:395
void initGinState(GinState *state, Relation index)
Definition: ginutil.c:102
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: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_object, RelationGetIndexScan(), and GinScanOpaqueData::tempCtx.

Referenced by ginhandler().

◆ ginendscan()

void ginendscan ( IndexScanDesc  scan)

Definition at line 503 of file ginscan.c.

504{
506
507 ginFreeScanKeys(so);
508
511
512 pfree(so);
513}
void ginFreeScanKeys(GinScanOpaque so)
Definition: ginscan.c:236
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 = palloc_object(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;
127 }
128 so->entries[so->totalentries++] = scanEntry;
129
130 return scanEntry;
131}
#define InvalidBlockNumber
Definition: block.h:33
#define InvalidBuffer
Definition: buf.h:25
uint32_t uint32
Definition: c.h:552
#define repalloc_array(pointer, type, count)
Definition: fe_memutils.h:78
#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
#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_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 158 of file ginscan.c.

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

237{
238 uint32 i;
239
240 if (so->keys == NULL)
241 return;
242
243 for (i = 0; i < so->totalentries; i++)
244 {
245 GinScanEntry entry = so->entries[i];
246
247 if (entry->buffer != InvalidBuffer)
248 ReleaseBuffer(entry->buffer);
249 if (entry->list)
250 pfree(entry->list);
251 if (entry->matchIterator)
253 if (entry->matchBitmap)
254 tbm_free(entry->matchBitmap);
255 }
256
258
259 so->keys = NULL;
260 so->nkeys = 0;
261 so->entries = NULL;
262 so->totalentries = 0;
263}
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 266 of file ginscan.c.

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

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

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

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

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

Referenced by ginFillScanKey().