PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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 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

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

Definition at line 25 of file ginscan.c.

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

Referenced by ginhandler().

26 {
27  IndexScanDesc scan;
28  GinScanOpaque so;
29 
30  /* no order by operators allowed */
31  Assert(norderbys == 0);
32 
33  scan = RelationGetIndexScan(rel, nkeys, norderbys);
34 
35  /* allocate private workspace */
36  so = (GinScanOpaque) palloc(sizeof(GinScanOpaqueData));
37  so->keys = NULL;
38  so->nkeys = 0;
40  "Gin scan temporary context",
43  "Gin scan key context",
45  initGinState(&so->ginstate, scan->indexRelation);
46 
47  scan->opaque = so;
48 
49  return scan;
50 }
Relation indexRelation
Definition: relscan.h:90
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
GinScanOpaqueData * GinScanOpaque
Definition: gin_private.h:364
MemoryContext keyCtx
Definition: gin_private.h:359
void initGinState(GinState *state, Relation index)
Definition: ginutil.c:86
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
GinScanKey keys
Definition: gin_private.h:352
MemoryContext tempCtx
Definition: gin_private.h:349
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
void * palloc(Size size)
Definition: mcxt.c:849
IndexScanDesc RelationGetIndexScan(Relation indexRelation, int nkeys, int norderbys)
Definition: genam.c:78
void ginendscan ( IndexScanDesc  scan)

Definition at line 432 of file ginscan.c.

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

Referenced by ginhandler().

433 {
434  GinScanOpaque so = (GinScanOpaque) scan->opaque;
435 
436  ginFreeScanKeys(so);
437 
440 
441  pfree(so);
442 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
void pfree(void *pointer)
Definition: mcxt.c:950
GinScanOpaqueData * GinScanOpaque
Definition: gin_private.h:364
MemoryContext keyCtx
Definition: gin_private.h:359
MemoryContext tempCtx
Definition: gin_private.h:349
void ginFreeScanKeys(GinScanOpaque so)
Definition: ginscan.c:232
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.

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

Referenced by ginFillScanKey().

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  if (extra_data == NULL)
73  {
74  for (i = 0; i < so->totalentries; i++)
75  {
76  GinScanEntry prevEntry = so->entries[i];
77 
78  if (prevEntry->extra_data == NULL &&
79  prevEntry->isPartialMatch == isPartialMatch &&
80  prevEntry->strategy == strategy &&
81  prevEntry->searchMode == searchMode &&
82  prevEntry->attnum == attnum &&
83  ginCompareEntries(ginstate, attnum,
84  prevEntry->queryKey,
85  prevEntry->queryCategory,
86  queryKey,
87  queryCategory) == 0)
88  {
89  /* Successful match */
90  return prevEntry;
91  }
92  }
93  }
94 
95  /* Nope, create a new entry */
96  scanEntry = (GinScanEntry) palloc(sizeof(GinScanEntryData));
97  scanEntry->queryKey = queryKey;
98  scanEntry->queryCategory = queryCategory;
99  scanEntry->isPartialMatch = isPartialMatch;
100  scanEntry->extra_data = extra_data;
101  scanEntry->strategy = strategy;
102  scanEntry->searchMode = searchMode;
103  scanEntry->attnum = attnum;
104 
105  scanEntry->buffer = InvalidBuffer;
106  ItemPointerSetMin(&scanEntry->curItem);
107  scanEntry->matchBitmap = NULL;
108  scanEntry->matchIterator = NULL;
109  scanEntry->matchResult = NULL;
110  scanEntry->list = NULL;
111  scanEntry->nlist = 0;
112  scanEntry->offset = InvalidOffsetNumber;
113  scanEntry->isFinished = false;
114  scanEntry->reduceResult = false;
115 
116  /* Add it to so's array */
117  if (so->totalentries >= so->allocentries)
118  {
119  so->allocentries *= 2;
120  so->entries = (GinScanEntry *)
121  repalloc(so->entries, so->allocentries * sizeof(GinScanEntry));
122  }
123  so->entries[so->totalentries++] = scanEntry;
124 
125  return scanEntry;
126 }
ItemPointerData curItem
Definition: gin_private.h:329
OffsetNumber offset
Definition: gin_private.h:339
TBMIterator * matchIterator
Definition: gin_private.h:333
#define InvalidBuffer
Definition: buf.h:25
int ginCompareEntries(GinState *ginstate, OffsetNumber attnum, Datum a, GinNullCategory categorya, Datum b, GinNullCategory categoryb)
Definition: ginutil.c:381
Pointer extra_data
Definition: gin_private.h:320
ItemPointerData * list
Definition: gin_private.h:337
OffsetNumber attnum
Definition: gin_private.h:323
unsigned int uint32
Definition: c.h:268
struct GinScanEntryData * GinScanEntry
Definition: gin_private.h:258
#define ItemPointerSetMin(p)
Definition: ginblock.h:157
TIDBitmap * matchBitmap
Definition: gin_private.h:332
StrategyNumber strategy
Definition: gin_private.h:321
TBMIterateResult * matchResult
Definition: gin_private.h:334
#define InvalidOffsetNumber
Definition: off.h:26
#define NULL
Definition: c.h:229
GinNullCategory queryCategory
Definition: gin_private.h:318
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:963
GinScanEntry * entries
Definition: gin_private.h:355
void * palloc(Size size)
Definition: mcxt.c:849
int i
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 132 of file ginscan.c.

References GinScanKeyData::additionalEntries, GinScanKeyData::attnum, GinState::canPartialMatch, GinScanKeyData::curItem, GinScanKeyData::curItemMatches, elog, GinScanKeyData::entryRes, ERROR, GinScanKeyData::extra_data, GIN_CAT_EMPTY_ITEM, GIN_CAT_EMPTY_QUERY, GIN_SEARCH_MODE_ALL, GIN_SEARCH_MODE_DEFAULT, GIN_SEARCH_MODE_EVERYTHING, GIN_SEARCH_MODE_INCLUDE_EMPTY, ginFillScanEntry(), ginInitConsistentFunction(), GinScanOpaqueData::ginstate, i, InvalidStrategy, GinScanKeyData::isFinished, ItemPointerSetMin, GinScanOpaqueData::keys, GinScanKeyData::nadditional, GinScanKeyData::nentries, GinScanOpaqueData::nkeys, GinScanKeyData::nrequired, NULL, GinScanKeyData::nuserentries, palloc(), palloc0(), GinScanKeyData::query, GinScanKeyData::queryCategories, GinScanKeyData::queryValues, GinScanKeyData::recheckCurItem, GinScanKeyData::requiredEntries, GinScanKeyData::scanEntry, GinScanKeyData::searchMode, and GinScanKeyData::strategy.

Referenced by ginNewScanKey().

137 {
138  GinScanKey key = &(so->keys[so->nkeys++]);
139  GinState *ginstate = &so->ginstate;
140  uint32 nUserQueryValues = nQueryValues;
141  uint32 i;
142 
143  /* Non-default search modes add one "hidden" entry to each key */
144  if (searchMode != GIN_SEARCH_MODE_DEFAULT)
145  nQueryValues++;
146  key->nentries = nQueryValues;
147  key->nuserentries = nUserQueryValues;
148 
149  key->scanEntry = (GinScanEntry *) palloc(sizeof(GinScanEntry) * nQueryValues);
150  key->entryRes = (GinTernaryValue *) palloc0(sizeof(GinTernaryValue) * nQueryValues);
151 
152  key->query = query;
153  key->queryValues = queryValues;
154  key->queryCategories = queryCategories;
155  key->extra_data = extra_data;
156  key->strategy = strategy;
157  key->searchMode = searchMode;
158  key->attnum = attnum;
159 
160  ItemPointerSetMin(&key->curItem);
161  key->curItemMatches = false;
162  key->recheckCurItem = false;
163  key->isFinished = false;
164  key->nrequired = 0;
165  key->nadditional = 0;
166  key->requiredEntries = NULL;
167  key->additionalEntries = NULL;
168 
169  ginInitConsistentFunction(ginstate, key);
170 
171  for (i = 0; i < nQueryValues; i++)
172  {
173  Datum queryKey;
174  GinNullCategory queryCategory;
175  bool isPartialMatch;
176  Pointer this_extra;
177 
178  if (i < nUserQueryValues)
179  {
180  /* set up normal entry using extractQueryFn's outputs */
181  queryKey = queryValues[i];
182  queryCategory = queryCategories[i];
183  isPartialMatch =
184  (ginstate->canPartialMatch[attnum - 1] && partial_matches)
185  ? partial_matches[i] : false;
186  this_extra = (extra_data) ? extra_data[i] : NULL;
187  }
188  else
189  {
190  /* set up hidden entry */
191  queryKey = (Datum) 0;
192  switch (searchMode)
193  {
195  queryCategory = GIN_CAT_EMPTY_ITEM;
196  break;
197  case GIN_SEARCH_MODE_ALL:
198  queryCategory = GIN_CAT_EMPTY_QUERY;
199  break;
201  queryCategory = GIN_CAT_EMPTY_QUERY;
202  break;
203  default:
204  elog(ERROR, "unexpected searchMode: %d", searchMode);
205  queryCategory = 0; /* keep compiler quiet */
206  break;
207  }
208  isPartialMatch = false;
209  this_extra = NULL;
210 
211  /*
212  * We set the strategy to a fixed value so that ginFillScanEntry
213  * can combine these entries for different scan keys. This is
214  * safe because the strategy value in the entry struct is only
215  * used for partial-match cases. It's OK to overwrite our local
216  * variable here because this is the last loop iteration.
217  */
218  strategy = InvalidStrategy;
219  }
220 
221  key->scanEntry[i] = ginFillScanEntry(so, attnum,
222  strategy, searchMode,
223  queryKey, queryCategory,
224  isPartialMatch, this_extra);
225  }
226 }
#define InvalidStrategy
Definition: stratnum.h:24
#define GIN_CAT_EMPTY_QUERY
Definition: ginblock.h:203
Datum * queryValues
Definition: gin_private.h:294
Pointer * extra_data
Definition: gin_private.h:296
#define GIN_SEARCH_MODE_EVERYTHING
Definition: gin.h:36
bool canPartialMatch[INDEX_MAX_KEYS]
Definition: gin_private.h:80
GinScanEntry * scanEntry
Definition: gin_private.h:268
#define GIN_SEARCH_MODE_ALL
Definition: gin.h:35
char * Pointer
Definition: c.h:245
#define GIN_SEARCH_MODE_INCLUDE_EMPTY
Definition: gin.h:34
#define ERROR
Definition: elog.h:43
signed char GinNullCategory
Definition: ginblock.h:197
char GinTernaryValue
Definition: gin.h:57
StrategyNumber strategy
Definition: gin_private.h:297
static GinScanEntry ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum, StrategyNumber strategy, int32 searchMode, Datum queryKey, GinNullCategory queryCategory, bool isPartialMatch, Pointer extra_data)
Definition: ginscan.c:57
GinTernaryValue * entryRes
Definition: gin_private.h:284
unsigned int uint32
Definition: c.h:268
OffsetNumber attnum
Definition: gin_private.h:299
#define ItemPointerSetMin(p)
Definition: ginblock.h:157
uint32 nuserentries
Definition: gin_private.h:265
GinScanKey keys
Definition: gin_private.h:352
GinScanEntry * requiredEntries
Definition: gin_private.h:278
void * palloc0(Size size)
Definition: mcxt.c:878
uintptr_t Datum
Definition: postgres.h:372
#define GIN_SEARCH_MODE_DEFAULT
Definition: gin.h:33
GinNullCategory * queryCategories
Definition: gin_private.h:295
#define NULL
Definition: c.h:229
ItemPointerData curItem
Definition: gin_private.h:308
void ginInitConsistentFunction(GinState *ginstate, GinScanKey key)
Definition: ginlogic.c:225
void * palloc(Size size)
Definition: mcxt.c:849
GinScanEntry * additionalEntries
Definition: gin_private.h:280
int i
#define elog
Definition: elog.h:219
#define GIN_CAT_EMPTY_ITEM
Definition: ginblock.h:201
void ginFreeScanKeys ( GinScanOpaque  so)

Definition at line 232 of file ginscan.c.

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

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

233 {
234  uint32 i;
235 
236  if (so->keys == NULL)
237  return;
238 
239  for (i = 0; i < so->totalentries; i++)
240  {
241  GinScanEntry entry = so->entries[i];
242 
243  if (entry->buffer != InvalidBuffer)
244  ReleaseBuffer(entry->buffer);
245  if (entry->list)
246  pfree(entry->list);
247  if (entry->matchIterator)
249  if (entry->matchBitmap)
250  tbm_free(entry->matchBitmap);
251  }
252 
254 
255  so->keys = NULL;
256  so->nkeys = 0;
257  so->entries = NULL;
258  so->totalentries = 0;
259 }
void tbm_end_iterate(TBMIterator *iterator)
Definition: tidbitmap.c:1172
TBMIterator * matchIterator
Definition: gin_private.h:333
#define InvalidBuffer
Definition: buf.h:25
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
ItemPointerData * list
Definition: gin_private.h:337
void pfree(void *pointer)
Definition: mcxt.c:950
void tbm_free(TIDBitmap *tbm)
Definition: tidbitmap.c:348
MemoryContext keyCtx
Definition: gin_private.h:359
unsigned int uint32
Definition: c.h:268
TIDBitmap * matchBitmap
Definition: gin_private.h:332
GinScanKey keys
Definition: gin_private.h:352
#define MemoryContextResetAndDeleteChildren(ctx)
Definition: memutils.h:67
#define NULL
Definition: c.h:229
GinScanEntry * entries
Definition: gin_private.h:355
int i
void ginNewScanKey ( IndexScanDesc  scan)

Definition at line 262 of file ginscan.c.

References GinScanOpaqueData::allocentries, DatumGetPointer, GinScanOpaqueData::entries, ereport, errcode(), errhint(), errmsg(), ERROR, GinState::extractQueryFn, FirstOffsetNumber, FunctionCall7Coll(), GIN_SEARCH_MODE_ALL, GIN_SEARCH_MODE_DEFAULT, GIN_SEARCH_MODE_EVERYTHING, ginFillScanKey(), ginGetStats(), GinScanOpaqueData::ginstate, GinStatsData::ginVersion, i, IndexScanDescData::indexRelation, InvalidStrategy, GinScanOpaqueData::isVoidRes, GinScanOpaqueData::keyCtx, IndexScanDescData::keyData, GinScanOpaqueData::keys, Max, MemoryContextSwitchTo(), GinScanOpaqueData::nkeys, NULL, IndexScanDescData::numberOfKeys, IndexScanDescData::opaque, palloc(), palloc0(), pgstat_count_index_scan, PointerGetDatum, RelationGetRelationName, ScanKeyData::sk_argument, ScanKeyData::sk_attno, ScanKeyData::sk_flags, SK_ISNULL, ScanKeyData::sk_strategy, GinState::supportCollation, GinScanOpaqueData::totalentries, and UInt16GetDatum.

Referenced by gingetbitmap().

263 {
264  ScanKey scankey = scan->keyData;
265  GinScanOpaque so = (GinScanOpaque) scan->opaque;
266  int i;
267  bool hasNullQuery = false;
268  MemoryContext oldCtx;
269 
270  /*
271  * Allocate all the scan key information in the key context. (If
272  * extractQuery leaks anything there, it won't be reset until the end of
273  * scan or rescan, but that's OK.)
274  */
275  oldCtx = MemoryContextSwitchTo(so->keyCtx);
276 
277  /* if no scan keys provided, allocate extra EVERYTHING GinScanKey */
278  so->keys = (GinScanKey)
279  palloc(Max(scan->numberOfKeys, 1) * sizeof(GinScanKeyData));
280  so->nkeys = 0;
281 
282  /* initialize expansible array of GinScanEntry pointers */
283  so->totalentries = 0;
284  so->allocentries = 32;
285  so->entries = (GinScanEntry *)
286  palloc(so->allocentries * sizeof(GinScanEntry));
287 
288  so->isVoidRes = false;
289 
290  for (i = 0; i < scan->numberOfKeys; i++)
291  {
292  ScanKey skey = &scankey[i];
293  Datum *queryValues;
294  int32 nQueryValues = 0;
295  bool *partial_matches = NULL;
296  Pointer *extra_data = NULL;
297  bool *nullFlags = NULL;
298  int32 searchMode = GIN_SEARCH_MODE_DEFAULT;
299 
300  /*
301  * We assume that GIN-indexable operators are strict, so a null query
302  * argument means an unsatisfiable query.
303  */
304  if (skey->sk_flags & SK_ISNULL)
305  {
306  so->isVoidRes = true;
307  break;
308  }
309 
310  /* OK to call the extractQueryFn */
311  queryValues = (Datum *)
313  so->ginstate.supportCollation[skey->sk_attno - 1],
314  skey->sk_argument,
315  PointerGetDatum(&nQueryValues),
317  PointerGetDatum(&partial_matches),
318  PointerGetDatum(&extra_data),
319  PointerGetDatum(&nullFlags),
320  PointerGetDatum(&searchMode)));
321 
322  /*
323  * If bogus searchMode is returned, treat as GIN_SEARCH_MODE_ALL; note
324  * in particular we don't allow extractQueryFn to select
325  * GIN_SEARCH_MODE_EVERYTHING.
326  */
327  if (searchMode < GIN_SEARCH_MODE_DEFAULT ||
328  searchMode > GIN_SEARCH_MODE_ALL)
329  searchMode = GIN_SEARCH_MODE_ALL;
330 
331  /* Non-default modes require the index to have placeholders */
332  if (searchMode != GIN_SEARCH_MODE_DEFAULT)
333  hasNullQuery = true;
334 
335  /*
336  * In default mode, no keys means an unsatisfiable query.
337  */
338  if (queryValues == NULL || nQueryValues <= 0)
339  {
340  if (searchMode == GIN_SEARCH_MODE_DEFAULT)
341  {
342  so->isVoidRes = true;
343  break;
344  }
345  nQueryValues = 0; /* ensure sane value */
346  }
347 
348  /*
349  * If the extractQueryFn didn't create a nullFlags array, create one,
350  * assuming that everything's non-null. Otherwise, run through the
351  * array and make sure each value is exactly 0 or 1; this ensures
352  * binary compatibility with the GinNullCategory representation. While
353  * at it, detect whether any null keys are present.
354  */
355  if (nullFlags == NULL)
356  nullFlags = (bool *) palloc0(nQueryValues * sizeof(bool));
357  else
358  {
359  int32 j;
360 
361  for (j = 0; j < nQueryValues; j++)
362  {
363  if (nullFlags[j])
364  {
365  nullFlags[j] = true; /* not any other nonzero value */
366  hasNullQuery = true;
367  }
368  }
369  }
370  /* now we can use the nullFlags as category codes */
371 
372  ginFillScanKey(so, skey->sk_attno,
373  skey->sk_strategy, searchMode,
374  skey->sk_argument, nQueryValues,
375  queryValues, (GinNullCategory *) nullFlags,
376  partial_matches, extra_data);
377  }
378 
379  /*
380  * If there are no regular scan keys, generate an EVERYTHING scankey to
381  * drive a full-index scan.
382  */
383  if (so->nkeys == 0 && !so->isVoidRes)
384  {
385  hasNullQuery = true;
388  (Datum) 0, 0,
389  NULL, NULL, NULL, NULL);
390  }
391 
392  /*
393  * If the index is version 0, it may be missing null and placeholder
394  * entries, which would render searches for nulls and full-index scans
395  * unreliable. Throw an error if so.
396  */
397  if (hasNullQuery && !so->isVoidRes)
398  {
399  GinStatsData ginStats;
400 
401  ginGetStats(scan->indexRelation, &ginStats);
402  if (ginStats.ginVersion < 1)
403  ereport(ERROR,
404  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
405  errmsg("old GIN indexes do not support whole-index scans nor searches for nulls"),
406  errhint("To fix this, do REINDEX INDEX \"%s\".",
408  }
409 
410  MemoryContextSwitchTo(oldCtx);
411 
413 }
#define InvalidStrategy
Definition: stratnum.h:24
Oid supportCollation[INDEX_MAX_KEYS]
Definition: gin_private.h:82
int errhint(const char *fmt,...)
Definition: elog.c:987
#define PointerGetDatum(X)
Definition: postgres.h:562
#define GIN_SEARCH_MODE_EVERYTHING
Definition: gin.h:36
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:575
signed int int32
Definition: c.h:256
Relation indexRelation
Definition: relscan.h:90
#define GIN_SEARCH_MODE_ALL
Definition: gin.h:35
char * Pointer
Definition: c.h:245
#define ERROR
Definition: elog.h:43
signed char GinNullCategory
Definition: ginblock.h:197
Datum FunctionCall7Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5, Datum arg6, Datum arg7)
Definition: fmgr.c:1182
struct GinScanKeyData * GinScanKey
Definition: gin_private.h:256
StrategyNumber sk_strategy
Definition: skey.h:68
GinScanOpaqueData * GinScanOpaque
Definition: gin_private.h:364
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:132
#define FirstOffsetNumber
Definition: off.h:27
MemoryContext keyCtx
Definition: gin_private.h:359
#define RelationGetRelationName(relation)
Definition: rel.h:436
#define pgstat_count_index_scan(rel)
Definition: pgstat.h:1266
FmgrInfo extractQueryFn[INDEX_MAX_KEYS]
Definition: gin_private.h:75
#define SK_ISNULL
Definition: skey.h:115
#define ereport(elevel, rest)
Definition: elog.h:122
GinScanKey keys
Definition: gin_private.h:352
void * palloc0(Size size)
Definition: mcxt.c:878
struct GinScanKeyData GinScanKeyData
uintptr_t Datum
Definition: postgres.h:372
void ginGetStats(Relation index, GinStatsData *stats)
Definition: ginutil.c:632
#define GIN_SEARCH_MODE_DEFAULT
Definition: gin.h:33
#define Max(x, y)
Definition: c.h:801
int sk_flags
Definition: skey.h:66
#define NULL
Definition: c.h:229
ScanKey keyData
Definition: relscan.h:94
int32 ginVersion
Definition: gin.h:48
#define DatumGetPointer(X)
Definition: postgres.h:555
GinScanEntry * entries
Definition: gin_private.h:355
void * palloc(Size size)
Definition: mcxt.c:849
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
Datum sk_argument
Definition: skey.h:72
#define UInt16GetDatum(X)
Definition: postgres.h:471
AttrNumber sk_attno
Definition: skey.h:67
void ginrescan ( IndexScanDesc  scan,
ScanKey  scankey,
int  nscankeys,
ScanKey  orderbys,
int  norderbys 
)

Definition at line 416 of file ginscan.c.

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

Referenced by ginhandler().

418 {
419  GinScanOpaque so = (GinScanOpaque) scan->opaque;
420 
421  ginFreeScanKeys(so);
422 
423  if (scankey && scan->numberOfKeys > 0)
424  {
425  memmove(scan->keyData, scankey,
426  scan->numberOfKeys * sizeof(ScanKeyData));
427  }
428 }
GinScanOpaqueData * GinScanOpaque
Definition: gin_private.h:364
#define memmove(d, s, c)
Definition: c.h:1059
ScanKey keyData
Definition: relscan.h:94
void ginFreeScanKeys(GinScanOpaque so)
Definition: ginscan.c:232