PostgreSQL Source Code git master
Loading...
Searching...
No Matches
spgscan.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/relscan.h"
#include "access/spgist_private.h"
#include "executor/instrument_node.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "storage/bufmgr.h"
#include "utils/datum.h"
#include "utils/float.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/rel.h"
Include dependency graph for spgscan.c:

Go to the source code of this file.

Typedefs

typedef void(* storeRes_func) (SpGistScanOpaque so, ItemPointer heapPtr, Datum leafValue, bool isNull, SpGistLeafTuple leafTuple, bool recheck, bool recheckDistances, double *distances)
 

Enumerations

enum  SpGistSpecialOffsetNumbers { SpGistBreakOffsetNumber = InvalidOffsetNumber , SpGistRedirectOffsetNumber = MaxOffsetNumber + 1 , SpGistErrorOffsetNumber = MaxOffsetNumber + 2 }
 

Functions

static int pairingheap_SpGistSearchItem_cmp (const pairingheap_node *a, const pairingheap_node *b, void *arg)
 
static void spgFreeSearchItem (SpGistScanOpaque so, SpGistSearchItem *item)
 
static void spgAddSearchItemToQueue (SpGistScanOpaque so, SpGistSearchItem *item)
 
static SpGistSearchItemspgAllocSearchItem (SpGistScanOpaque so, bool isnull, double *distances)
 
static void spgAddStartItem (SpGistScanOpaque so, bool isnull)
 
static void resetSpGistScanOpaque (SpGistScanOpaque so)
 
static void spgPrepareScanKeys (IndexScanDesc scan)
 
IndexScanDesc spgbeginscan (Relation rel, int keysz, int orderbysz)
 
void spgrescan (IndexScanDesc scan, ScanKey scankey, int nscankeys, ScanKey orderbys, int norderbys)
 
void spgendscan (IndexScanDesc scan)
 
static SpGistSearchItemspgNewHeapItem (SpGistScanOpaque so, int level, SpGistLeafTuple leafTuple, Datum leafValue, bool recheck, bool recheckDistances, bool isnull, double *distances)
 
static bool spgLeafTest (SpGistScanOpaque so, SpGistSearchItem *item, SpGistLeafTuple leafTuple, bool isnull, bool *reportedSome, storeRes_func storeRes)
 
static void spgInitInnerConsistentIn (spgInnerConsistentIn *in, SpGistScanOpaque so, SpGistSearchItem *item, SpGistInnerTuple innerTuple)
 
static SpGistSearchItemspgMakeInnerItem (SpGistScanOpaque so, SpGistSearchItem *parentItem, SpGistNodeTuple tuple, spgInnerConsistentOut *out, int i, bool isnull, double *distances)
 
static void spgInnerTest (SpGistScanOpaque so, SpGistSearchItem *item, SpGistInnerTuple innerTuple, bool isnull)
 
static SpGistSearchItemspgGetNextQueueItem (SpGistScanOpaque so)
 
static OffsetNumber spgTestLeafTuple (SpGistScanOpaque so, SpGistSearchItem *item, Page page, OffsetNumber offset, bool isnull, bool isroot, bool *reportedSome, storeRes_func storeRes)
 
static void spgWalk (Relation index, SpGistScanOpaque so, bool scanWholeIndex, storeRes_func storeRes)
 
static void storeBitmap (SpGistScanOpaque so, ItemPointer heapPtr, Datum leafValue, bool isnull, SpGistLeafTuple leafTuple, bool recheck, bool recheckDistances, double *distances)
 
int64 spggetbitmap (IndexScanDesc scan, TIDBitmap *tbm)
 
static void storeGettuple (SpGistScanOpaque so, ItemPointer heapPtr, Datum leafValue, bool isnull, SpGistLeafTuple leafTuple, bool recheck, bool recheckDistances, double *nonNullDistances)
 
bool spggettuple (IndexScanDesc scan, ScanDirection dir)
 
bool spgcanreturn (Relation index, int attno)
 

Typedef Documentation

◆ storeRes_func

typedef void(* storeRes_func) (SpGistScanOpaque so, ItemPointer heapPtr, Datum leafValue, bool isNull, SpGistLeafTuple leafTuple, bool recheck, bool recheckDistances, double *distances)

Definition at line 31 of file spgscan.c.

Enumeration Type Documentation

◆ SpGistSpecialOffsetNumbers

Enumerator
SpGistBreakOffsetNumber 
SpGistRedirectOffsetNumber 
SpGistErrorOffsetNumber 

Definition at line 750 of file spgscan.c.

751{
755};
#define InvalidOffsetNumber
Definition off.h:26
#define MaxOffsetNumber
Definition off.h:28
@ SpGistErrorOffsetNumber
Definition spgscan.c:754
@ SpGistBreakOffsetNumber
Definition spgscan.c:752
@ SpGistRedirectOffsetNumber
Definition spgscan.c:753

Function Documentation

◆ pairingheap_SpGistSearchItem_cmp()

static int pairingheap_SpGistSearchItem_cmp ( const pairingheap_node a,
const pairingheap_node b,
void arg 
)
static

Definition at line 42 of file spgscan.c.

44{
45 const SpGistSearchItem *sa = (const SpGistSearchItem *) a;
46 const SpGistSearchItem *sb = (const SpGistSearchItem *) b;
48 int i;
49
50 if (sa->isNull)
51 {
52 if (!sb->isNull)
53 return -1;
54 }
55 else if (sb->isNull)
56 {
57 return 1;
58 }
59 else
60 {
61 /* Order according to distance comparison */
62 for (i = 0; i < so->numberOfNonNullOrderBys; i++)
63 {
64 if (isnan(sa->distances[i]) && isnan(sb->distances[i]))
65 continue; /* NaN == NaN */
66 if (isnan(sa->distances[i]))
67 return -1; /* NaN > number */
68 if (isnan(sb->distances[i]))
69 return 1; /* number < NaN */
70 if (sa->distances[i] != sb->distances[i])
71 return (sa->distances[i] < sb->distances[i]) ? 1 : -1;
72 }
73 }
74
75 /* Leaf items go before inner pages, to ensure a depth-first search */
76 if (sa->isLeaf && !sb->isLeaf)
77 return 1;
78 if (!sa->isLeaf && sb->isLeaf)
79 return -1;
80
81 return 0;
82}
int b
Definition isn.c:74
int a
Definition isn.c:73
int i
Definition isn.c:77
void * arg
static int fb(int x)
SpGistScanOpaqueData * SpGistScanOpaque

References a, arg, b, fb(), and i.

Referenced by resetSpGistScanOpaque().

◆ resetSpGistScanOpaque()

static void resetSpGistScanOpaque ( SpGistScanOpaque  so)
static

Definition at line 155 of file spgscan.c.

156{
158
159 MemoryContextReset(so->traversalCxt);
160
161 oldCtx = MemoryContextSwitchTo(so->traversalCxt);
162
163 /* initialize queue only for distance-ordered scans */
165
166 if (so->searchNulls)
167 /* Add a work item to scan the null index entries */
168 spgAddStartItem(so, true);
169
170 if (so->searchNonNulls)
171 /* Add a work item to scan the non-null index entries */
172 spgAddStartItem(so, false);
173
175
176 if (so->numberOfOrderBys > 0)
177 {
178 /* Must pfree distances to avoid memory leak */
179 int i;
180
181 for (i = 0; i < so->nPtrs; i++)
182 if (so->distances[i])
183 pfree(so->distances[i]);
184 }
185
186 if (so->want_itup)
187 {
188 /* Must pfree reconstructed tuples to avoid memory leak */
189 int i;
190
191 for (i = 0; i < so->nPtrs; i++)
192 pfree(so->reconTups[i]);
193 }
194 so->iPtr = so->nPtrs = 0;
195}
void MemoryContextReset(MemoryContext context)
Definition mcxt.c:403
void pfree(void *pointer)
Definition mcxt.c:1616
pairingheap * pairingheap_allocate(pairingheap_comparator compare, void *arg)
Definition pairingheap.c:42
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
static int pairingheap_SpGistSearchItem_cmp(const pairingheap_node *a, const pairingheap_node *b, void *arg)
Definition spgscan.c:42
static void spgAddStartItem(SpGistScanOpaque so, bool isnull)
Definition spgscan.c:131

References fb(), i, MemoryContextReset(), MemoryContextSwitchTo(), pairingheap_allocate(), pairingheap_SpGistSearchItem_cmp(), pfree(), and spgAddStartItem().

Referenced by spgrescan().

◆ spgAddSearchItemToQueue()

static void spgAddSearchItemToQueue ( SpGistScanOpaque  so,
SpGistSearchItem item 
)
static

Definition at line 109 of file spgscan.c.

110{
111 pairingheap_add(so->scanQueue, &item->phNode);
112}
void pairingheap_add(pairingheap *heap, pairingheap_node *node)
pairingheap_node phNode

References fb(), pairingheap_add(), and SpGistSearchItem::phNode.

Referenced by spgAddStartItem(), spgInnerTest(), and spgLeafTest().

◆ spgAddStartItem()

static void spgAddStartItem ( SpGistScanOpaque  so,
bool  isnull 
)
static

Definition at line 131 of file spgscan.c.

132{
134 spgAllocSearchItem(so, isnull, so->zeroDistances);
135
136 ItemPointerSet(&startEntry->heapPtr,
139 startEntry->isLeaf = false;
140 startEntry->level = 0;
141 startEntry->value = (Datum) 0;
142 startEntry->leafTuple = NULL;
143 startEntry->traversalValue = NULL;
144 startEntry->recheck = false;
145 startEntry->recheckDistances = false;
146
148}
static void ItemPointerSet(ItemPointerData *pointer, BlockNumber blockNumber, OffsetNumber offNum)
Definition itemptr.h:135
#define FirstOffsetNumber
Definition off.h:27
uint64_t Datum
Definition postgres.h:70
#define SPGIST_NULL_BLKNO
#define SPGIST_ROOT_BLKNO
static void spgAddSearchItemToQueue(SpGistScanOpaque so, SpGistSearchItem *item)
Definition spgscan.c:109
static SpGistSearchItem * spgAllocSearchItem(SpGistScanOpaque so, bool isnull, double *distances)
Definition spgscan.c:115

References fb(), FirstOffsetNumber, ItemPointerSet(), spgAddSearchItemToQueue(), spgAllocSearchItem(), SPGIST_NULL_BLKNO, and SPGIST_ROOT_BLKNO.

Referenced by resetSpGistScanOpaque().

◆ spgAllocSearchItem()

static SpGistSearchItem * spgAllocSearchItem ( SpGistScanOpaque  so,
bool  isnull,
double distances 
)
static

Definition at line 115 of file spgscan.c.

116{
117 /* allocate distance array only for non-NULL items */
118 SpGistSearchItem *item =
119 palloc(SizeOfSpGistSearchItem(isnull ? 0 : so->numberOfNonNullOrderBys));
120
121 item->isNull = isnull;
122
123 if (!isnull && so->numberOfNonNullOrderBys > 0)
124 memcpy(item->distances, distances,
125 sizeof(item->distances[0]) * so->numberOfNonNullOrderBys);
126
127 return item;
128}
void * palloc(Size size)
Definition mcxt.c:1387
#define SizeOfSpGistSearchItem(n_distances)
double distances[FLEXIBLE_ARRAY_MEMBER]

References SpGistSearchItem::distances, fb(), SpGistSearchItem::isNull, palloc(), and SizeOfSpGistSearchItem.

Referenced by spgAddStartItem(), spgMakeInnerItem(), and spgNewHeapItem().

◆ spgbeginscan()

IndexScanDesc spgbeginscan ( Relation  rel,
int  keysz,
int  orderbysz 
)

Definition at line 305 of file spgscan.c.

306{
307 IndexScanDesc scan;
309 int i;
310
311 scan = RelationGetIndexScan(rel, keysz, orderbysz);
312
314 if (keysz > 0)
315 so->keyData = palloc_array(ScanKeyData, keysz);
316 else
317 so->keyData = NULL;
318 initSpGistState(&so->state, scan->indexRelation);
319
321 "SP-GiST search temporary context",
324 "SP-GiST traversal-value context",
326
327 /*
328 * Set up reconTupDesc and xs_hitupdesc in case it's an index-only scan,
329 * making sure that the key column is shown as being of type attType.
330 * (It's rather annoying to do this work when it might be wasted, but for
331 * most opclasses we can re-use the index reldesc instead of making one.)
332 */
333 so->reconTupDesc = scan->xs_hitupdesc =
334 getSpGistTupleDesc(rel, &so->state.attType);
335
336 /* Allocate various arrays needed for order-by scans */
337 if (scan->numberOfOrderBys > 0)
338 {
339 /* This will be filled in spgrescan, but allocate the space here */
340 so->orderByTypes = palloc_array(Oid, scan->numberOfOrderBys);
341 so->nonNullOrderByOffsets = palloc_array(int, scan->numberOfOrderBys);
342
343 /* These arrays have constant contents, so we can fill them now */
344 so->zeroDistances = palloc_array(double, scan->numberOfOrderBys);
345 so->infDistances = palloc_array(double, scan->numberOfOrderBys);
346
347 for (i = 0; i < scan->numberOfOrderBys; i++)
348 {
349 so->zeroDistances[i] = 0.0;
350 so->infDistances[i] = get_float8_infinity();
351 }
352
354 scan->xs_orderbynulls = palloc_array(bool, scan->numberOfOrderBys);
355 memset(scan->xs_orderbynulls, true,
356 sizeof(bool) * scan->numberOfOrderBys);
357 }
358
359 fmgr_info_copy(&so->innerConsistentFn,
362
363 fmgr_info_copy(&so->leafConsistentFn,
366
367 so->indexCollation = rel->rd_indcollation[0];
368
369 scan->opaque = so;
370
371 return scan;
372}
#define palloc_array(type, count)
Definition fe_memutils.h:76
#define palloc0_array(type, count)
Definition fe_memutils.h:77
#define palloc0_object(type)
Definition fe_memutils.h:75
static float8 get_float8_infinity(void)
Definition float.h:65
void fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo, MemoryContext destcxt)
Definition fmgr.c:581
IndexScanDesc RelationGetIndexScan(Relation indexRelation, int nkeys, int norderbys)
Definition genam.c:80
FmgrInfo * index_getprocinfo(Relation irel, AttrNumber attnum, uint16 procnum)
Definition indexam.c:917
MemoryContext CurrentMemoryContext
Definition mcxt.c:160
#define AllocSetContextCreate
Definition memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition memutils.h:160
unsigned int Oid
#define SPGIST_LEAF_CONSISTENT_PROC
Definition spgist.h:27
#define SPGIST_INNER_CONSISTENT_PROC
Definition spgist.h:26
void initSpGistState(SpGistState *state, Relation index)
Definition spgutils.c:349
TupleDesc getSpGistTupleDesc(Relation index, SpGistTypeDesc *keyType)
Definition spgutils.c:316
bool * xs_orderbynulls
Definition relscan.h:188
struct TupleDescData * xs_hitupdesc
Definition relscan.h:171
Relation indexRelation
Definition relscan.h:138
Datum * xs_orderbyvals
Definition relscan.h:187
Oid * rd_indcollation
Definition rel.h:217

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, CurrentMemoryContext, fb(), fmgr_info_copy(), get_float8_infinity(), getSpGistTupleDesc(), i, index_getprocinfo(), IndexScanDescData::indexRelation, initSpGistState(), IndexScanDescData::numberOfOrderBys, IndexScanDescData::opaque, palloc0_array, palloc0_object, palloc_array, RelationData::rd_indcollation, RelationGetIndexScan(), SPGIST_INNER_CONSISTENT_PROC, SPGIST_LEAF_CONSISTENT_PROC, IndexScanDescData::xs_hitupdesc, IndexScanDescData::xs_orderbynulls, and IndexScanDescData::xs_orderbyvals.

Referenced by spghandler().

◆ spgcanreturn()

bool spgcanreturn ( Relation  index,
int  attno 
)

Definition at line 1078 of file spgscan.c.

1079{
1080 SpGistCache *cache;
1081
1082 /* INCLUDE attributes can always be fetched for index-only scans */
1083 if (attno > 1)
1084 return true;
1085
1086 /* We can do it if the opclass config function says so */
1087 cache = spgGetCache(index);
1088
1089 return cache->config.canReturnData;
1090}
SpGistCache * spgGetCache(Relation index)
Definition spgutils.c:189
spgConfigOut config
Definition type.h:96
bool canReturnData
Definition spgist.h:46

References spgConfigOut::canReturnData, SpGistCache::config, and spgGetCache().

Referenced by spghandler().

◆ spgendscan()

void spgendscan ( IndexScanDesc  scan)

Definition at line 424 of file spgscan.c.

425{
427
428 MemoryContextDelete(so->tempCxt);
429 MemoryContextDelete(so->traversalCxt);
430
431 if (so->keyData)
432 pfree(so->keyData);
433
434 if (so->state.leafTupDesc &&
435 so->state.leafTupDesc != RelationGetDescr(so->state.index))
436 FreeTupleDesc(so->state.leafTupDesc);
437
438 if (so->state.deadTupleStorage)
439 pfree(so->state.deadTupleStorage);
440
441 if (scan->numberOfOrderBys > 0)
442 {
443 pfree(so->orderByTypes);
444 pfree(so->nonNullOrderByOffsets);
445 pfree(so->zeroDistances);
446 pfree(so->infDistances);
447 pfree(scan->xs_orderbyvals);
448 pfree(scan->xs_orderbynulls);
449 }
450
451 pfree(so);
452}
void MemoryContextDelete(MemoryContext context)
Definition mcxt.c:472
#define RelationGetDescr(relation)
Definition rel.h:540
void FreeTupleDesc(TupleDesc tupdesc)
Definition tupdesc.c:502

References fb(), FreeTupleDesc(), MemoryContextDelete(), IndexScanDescData::numberOfOrderBys, IndexScanDescData::opaque, pfree(), RelationGetDescr, IndexScanDescData::xs_orderbynulls, and IndexScanDescData::xs_orderbyvals.

Referenced by spghandler().

◆ spgFreeSearchItem()

static void spgFreeSearchItem ( SpGistScanOpaque  so,
SpGistSearchItem item 
)
static

Definition at line 85 of file spgscan.c.

86{
87 /* value is of type attType if isLeaf, else of type attLeafType */
88 /* (no, that is not backwards; yes, it's confusing) */
89 if (!(item->isLeaf ? so->state.attType.attbyval :
90 so->state.attLeafType.attbyval) &&
91 DatumGetPointer(item->value) != NULL)
93
94 if (item->leafTuple)
95 pfree(item->leafTuple);
96
97 if (item->traversalValue)
98 pfree(item->traversalValue);
99
100 pfree(item);
101}
static struct @172 value
bool attbyval
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:342
SpGistLeafTuple leafTuple

References DatumGetPointer(), fb(), SpGistSearchItem::isLeaf, SpGistSearchItem::leafTuple, pfree(), SpGistSearchItem::traversalValue, and SpGistSearchItem::value.

Referenced by spgWalk().

◆ spggetbitmap()

int64 spggetbitmap ( IndexScanDesc  scan,
TIDBitmap tbm 
)

Definition at line 937 of file spgscan.c.

938{
940
941 /* Copy want_itup to *so so we don't need to pass it around separately */
942 so->want_itup = false;
943
944 so->tbm = tbm;
945 so->ntids = 0;
946
947 spgWalk(scan->indexRelation, so, true, storeBitmap);
948
949 return so->ntids;
950}
static void spgWalk(Relation index, SpGistScanOpaque so, bool scanWholeIndex, storeRes_func storeRes)
Definition spgscan.c:812
static void storeBitmap(SpGistScanOpaque so, ItemPointer heapPtr, Datum leafValue, bool isnull, SpGistLeafTuple leafTuple, bool recheck, bool recheckDistances, double *distances)
Definition spgscan.c:926

References fb(), IndexScanDescData::indexRelation, IndexScanDescData::opaque, spgWalk(), and storeBitmap().

Referenced by spghandler().

◆ spgGetNextQueueItem()

static SpGistSearchItem * spgGetNextQueueItem ( SpGistScanOpaque  so)
static

Definition at line 741 of file spgscan.c.

742{
743 if (pairingheap_is_empty(so->scanQueue))
744 return NULL; /* Done when both heaps are empty */
745
746 /* Return item; caller is responsible to pfree it */
747 return (SpGistSearchItem *) pairingheap_remove_first(so->scanQueue);
748}
pairingheap_node * pairingheap_remove_first(pairingheap *heap)
#define pairingheap_is_empty(h)
Definition pairingheap.h:99

References fb(), pairingheap_is_empty, and pairingheap_remove_first().

Referenced by spgWalk().

◆ spggettuple()

bool spggettuple ( IndexScanDesc  scan,
ScanDirection  dir 
)

Definition at line 1021 of file spgscan.c.

1022{
1024
1025 if (dir != ForwardScanDirection)
1026 elog(ERROR, "SP-GiST only supports forward scan direction");
1027
1028 /* Copy want_itup to *so so we don't need to pass it around separately */
1029 so->want_itup = scan->xs_want_itup;
1030
1031 for (;;)
1032 {
1033 if (so->iPtr < so->nPtrs)
1034 {
1035 /* continuing to return reported tuples */
1036 scan->xs_heaptid = so->heapPtrs[so->iPtr];
1037 scan->xs_recheck = so->recheck[so->iPtr];
1038 scan->xs_hitup = so->reconTups[so->iPtr];
1039
1040 if (so->numberOfOrderBys > 0)
1041 index_store_float8_orderby_distances(scan, so->orderByTypes,
1042 so->distances[so->iPtr],
1043 so->recheckDistances[so->iPtr]);
1044 so->iPtr++;
1045 return true;
1046 }
1047
1048 if (so->numberOfOrderBys > 0)
1049 {
1050 /* Must pfree distances to avoid memory leak */
1051 int i;
1052
1053 for (i = 0; i < so->nPtrs; i++)
1054 if (so->distances[i])
1055 pfree(so->distances[i]);
1056 }
1057
1058 if (so->want_itup)
1059 {
1060 /* Must pfree reconstructed tuples to avoid memory leak */
1061 int i;
1062
1063 for (i = 0; i < so->nPtrs; i++)
1064 pfree(so->reconTups[i]);
1065 }
1066 so->iPtr = so->nPtrs = 0;
1067
1068 spgWalk(scan->indexRelation, so, false, storeGettuple);
1069
1070 if (so->nPtrs == 0)
1071 break; /* must have completed scan */
1072 }
1073
1074 return false;
1075}
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
void index_store_float8_orderby_distances(IndexScanDesc scan, Oid *orderByTypes, IndexOrderByDistance *distances, bool recheckOrderBy)
Definition indexam.c:985
@ ForwardScanDirection
Definition sdir.h:28
static void storeGettuple(SpGistScanOpaque so, ItemPointer heapPtr, Datum leafValue, bool isnull, SpGistLeafTuple leafTuple, bool recheck, bool recheckDistances, double *nonNullDistances)
Definition spgscan.c:954
HeapTuple xs_hitup
Definition relscan.h:170
ItemPointerData xs_heaptid
Definition relscan.h:173

References elog, ERROR, fb(), ForwardScanDirection, i, index_store_float8_orderby_distances(), IndexScanDescData::indexRelation, IndexScanDescData::opaque, pfree(), spgWalk(), storeGettuple(), IndexScanDescData::xs_heaptid, IndexScanDescData::xs_hitup, IndexScanDescData::xs_recheck, and IndexScanDescData::xs_want_itup.

Referenced by spghandler().

◆ spgInitInnerConsistentIn()

static void spgInitInnerConsistentIn ( spgInnerConsistentIn in,
SpGistScanOpaque  so,
SpGistSearchItem item,
SpGistInnerTuple  innerTuple 
)
static

Definition at line 601 of file spgscan.c.

605{
606 in->scankeys = so->keyData;
607 in->orderbys = so->orderByData;
608 in->nkeys = so->numberOfKeys;
609 in->norderbys = so->numberOfNonNullOrderBys;
610 Assert(!item->isLeaf); /* else reconstructedValue would be wrong type */
611 in->reconstructedValue = item->value;
612 in->traversalMemoryContext = so->traversalCxt;
613 in->traversalValue = item->traversalValue;
614 in->level = item->level;
615 in->returnData = so->want_itup;
616 in->allTheSame = innerTuple->allTheSame;
617 in->hasPrefix = (innerTuple->prefixSize > 0);
618 in->prefixDatum = SGITDATUM(innerTuple, &so->state);
619 in->nNodes = innerTuple->nNodes;
621}
#define Assert(condition)
Definition c.h:873
#define SGITDATUM(x, s)
Datum * spgExtractNodeLabels(SpGistState *state, SpGistInnerTuple innerTuple)
Definition spgutils.c:1161
Datum reconstructedValue
Definition spgist.h:140
void * traversalValue
Definition spgist.h:141
MemoryContext traversalMemoryContext
Definition spgist.h:142

References spgInnerConsistentIn::allTheSame, Assert, fb(), spgInnerConsistentIn::hasPrefix, SpGistSearchItem::isLeaf, spgInnerConsistentIn::level, SpGistSearchItem::level, spgInnerConsistentIn::nkeys, spgInnerConsistentIn::nNodes, spgInnerConsistentIn::nodeLabels, spgInnerConsistentIn::norderbys, spgInnerConsistentIn::orderbys, spgInnerConsistentIn::prefixDatum, spgInnerConsistentIn::reconstructedValue, spgInnerConsistentIn::returnData, spgInnerConsistentIn::scankeys, SGITDATUM, spgExtractNodeLabels(), spgInnerConsistentIn::traversalMemoryContext, spgInnerConsistentIn::traversalValue, SpGistSearchItem::traversalValue, and SpGistSearchItem::value.

Referenced by spgInnerTest().

◆ spgInnerTest()

static void spgInnerTest ( SpGistScanOpaque  so,
SpGistSearchItem item,
SpGistInnerTuple  innerTuple,
bool  isnull 
)
static

Definition at line 662 of file spgscan.c.

664{
667 int nNodes = innerTuple->nNodes;
668 int i;
669
670 memset(&out, 0, sizeof(out));
671
672 if (!isnull)
673 {
675
677
678 /* use user-defined inner consistent method */
679 FunctionCall2Coll(&so->innerConsistentFn,
680 so->indexCollation,
681 PointerGetDatum(&in),
682 PointerGetDatum(&out));
683 }
684 else
685 {
686 /* force all children to be visited */
687 out.nNodes = nNodes;
688 out.nodeNumbers = palloc_array(int, nNodes);
689 for (i = 0; i < nNodes; i++)
690 out.nodeNumbers[i] = i;
691 }
692
693 /* If allTheSame, they should all or none of them match */
694 if (innerTuple->allTheSame && out.nNodes != 0 && out.nNodes != nNodes)
695 elog(ERROR, "inconsistent inner_consistent results for allTheSame inner tuple");
696
697 if (out.nNodes)
698 {
699 /* collect node pointers */
700 SpGistNodeTuple node;
702
703 SGITITERATE(innerTuple, i, node)
704 {
705 nodes[i] = node;
706 }
707
708 MemoryContextSwitchTo(so->traversalCxt);
709
710 for (i = 0; i < out.nNodes; i++)
711 {
712 int nodeN = out.nodeNumbers[i];
714 double *distances;
715
716 Assert(nodeN >= 0 && nodeN < nNodes);
717
718 node = nodes[nodeN];
719
720 if (!ItemPointerIsValid(&node->t_tid))
721 continue;
722
723 /*
724 * Use infinity distances if innerConsistentFn() failed to return
725 * them or if is a NULL item (their distances are really unused).
726 */
727 distances = out.distances ? out.distances[i] : so->infDistances;
728
729 innerItem = spgMakeInnerItem(so, item, node, &out, i, isnull,
730 distances);
731
733 }
734 }
735
737}
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition fmgr.c:1150
static bool ItemPointerIsValid(const ItemPointerData *pointer)
Definition itemptr.h:83
static Datum PointerGetDatum(const void *X)
Definition postgres.h:352
#define SGITITERATE(x, i, nt)
static void spgInitInnerConsistentIn(spgInnerConsistentIn *in, SpGistScanOpaque so, SpGistSearchItem *item, SpGistInnerTuple innerTuple)
Definition spgscan.c:601
static SpGistSearchItem * spgMakeInnerItem(SpGistScanOpaque so, SpGistSearchItem *parentItem, SpGistNodeTuple tuple, spgInnerConsistentOut *out, int i, bool isnull, double *distances)
Definition spgscan.c:624
ItemPointerData t_tid
Definition itup.h:37
double ** distances
Definition spgist.h:161

References Assert, spgInnerConsistentOut::distances, elog, ERROR, fb(), FunctionCall2Coll(), i, ItemPointerIsValid(), MemoryContextSwitchTo(), spgInnerConsistentOut::nNodes, spgInnerConsistentOut::nodeNumbers, palloc_array, PointerGetDatum(), SGITITERATE, spgAddSearchItemToQueue(), spgInitInnerConsistentIn(), spgMakeInnerItem(), and IndexTupleData::t_tid.

Referenced by spgWalk().

◆ spgLeafTest()

static bool spgLeafTest ( SpGistScanOpaque  so,
SpGistSearchItem item,
SpGistLeafTuple  leafTuple,
bool  isnull,
bool reportedSome,
storeRes_func  storeRes 
)
static

Definition at line 511 of file spgscan.c.

514{
515 Datum leafValue;
516 double *distances;
517 bool result;
518 bool recheck;
519 bool recheckDistances;
520
521 if (isnull)
522 {
523 /* Should not have arrived on a nulls page unless nulls are wanted */
524 Assert(so->searchNulls);
525 leafValue = (Datum) 0;
526 distances = NULL;
527 recheck = false;
528 recheckDistances = false;
529 result = true;
530 }
531 else
532 {
535
536 /* use temp context for calling leaf_consistent */
538
539 in.scankeys = so->keyData;
540 in.nkeys = so->numberOfKeys;
541 in.orderbys = so->orderByData;
542 in.norderbys = so->numberOfNonNullOrderBys;
543 Assert(!item->isLeaf); /* else reconstructedValue would be wrong type */
544 in.reconstructedValue = item->value;
546 in.level = item->level;
547 in.returnData = so->want_itup;
548 in.leafDatum = SGLTDATUM(leafTuple, &so->state);
549
550 out.leafValue = (Datum) 0;
551 out.recheck = false;
552 out.distances = NULL;
553 out.recheckDistances = false;
554
555 result = DatumGetBool(FunctionCall2Coll(&so->leafConsistentFn,
556 so->indexCollation,
557 PointerGetDatum(&in),
558 PointerGetDatum(&out)));
559 recheck = out.recheck;
560 recheckDistances = out.recheckDistances;
561 leafValue = out.leafValue;
562 distances = out.distances;
563
565 }
566
567 if (result)
568 {
569 /* item passes the scankeys */
570 if (so->numberOfNonNullOrderBys > 0)
571 {
572 /* the scan is ordered -> add the item to the queue */
575 leafTuple,
576 leafValue,
577 recheck,
578 recheckDistances,
579 isnull,
580 distances);
581
583
585 }
586 else
587 {
588 /* non-ordered scan, so report the item right away */
589 Assert(!recheckDistances);
590 storeRes(so, &leafTuple->heapPtr, leafValue, isnull,
591 leafTuple, recheck, false, NULL);
592 *reportedSome = true;
593 }
594 }
595
596 return result;
597}
static bool DatumGetBool(Datum X)
Definition postgres.h:100
#define SGLTDATUM(x, s)
static SpGistSearchItem * spgNewHeapItem(SpGistScanOpaque so, int level, SpGistLeafTuple leafTuple, Datum leafValue, bool recheck, bool recheckDistances, bool isnull, double *distances)
Definition spgscan.c:458
ItemPointerData heapPtr
Datum reconstructedValue
Definition spgist.h:175
void * traversalValue
Definition spgist.h:176
double * distances
Definition spgist.h:188

References Assert, DatumGetBool(), spgLeafConsistentOut::distances, fb(), FunctionCall2Coll(), SpGistLeafTupleData::heapPtr, SpGistSearchItem::isLeaf, spgLeafConsistentIn::leafDatum, spgLeafConsistentOut::leafValue, spgLeafConsistentIn::level, SpGistSearchItem::level, MemoryContextSwitchTo(), spgLeafConsistentIn::nkeys, spgLeafConsistentIn::norderbys, spgLeafConsistentIn::orderbys, PointerGetDatum(), spgLeafConsistentOut::recheck, spgLeafConsistentOut::recheckDistances, spgLeafConsistentIn::reconstructedValue, spgLeafConsistentIn::returnData, spgLeafConsistentIn::scankeys, SGLTDATUM, spgAddSearchItemToQueue(), spgNewHeapItem(), spgLeafConsistentIn::traversalValue, SpGistSearchItem::traversalValue, and SpGistSearchItem::value.

Referenced by spgTestLeafTuple().

◆ spgMakeInnerItem()

static SpGistSearchItem * spgMakeInnerItem ( SpGistScanOpaque  so,
SpGistSearchItem parentItem,
SpGistNodeTuple  tuple,
spgInnerConsistentOut out,
int  i,
bool  isnull,
double distances 
)
static

Definition at line 624 of file spgscan.c.

629{
630 SpGistSearchItem *item = spgAllocSearchItem(so, isnull, distances);
631
632 item->heapPtr = tuple->t_tid;
633 item->level = out->levelAdds ? parentItem->level + out->levelAdds[i]
634 : parentItem->level;
635
636 /* Must copy value out of temp context */
637 /* (recall that reconstructed values are of type leafType) */
638 item->value = out->reconstructedValues
640 so->state.attLeafType.attbyval,
641 so->state.attLeafType.attlen)
642 : (Datum) 0;
643
644 item->leafTuple = NULL;
645
646 /*
647 * Elements of out.traversalValues should be allocated in
648 * in.traversalMemoryContext, which is actually a long lived context of
649 * index scan.
650 */
651 item->traversalValue =
652 out->traversalValues ? out->traversalValues[i] : NULL;
653
654 item->isLeaf = false;
655 item->recheck = false;
656 item->recheckDistances = false;
657
658 return item;
659}
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition datum.c:132
ItemPointerData heapPtr
void ** traversalValues
Definition spgist.h:160
Datum * reconstructedValues
Definition spgist.h:159

References datumCopy(), fb(), SpGistSearchItem::heapPtr, i, SpGistSearchItem::isLeaf, SpGistSearchItem::leafTuple, SpGistSearchItem::level, spgInnerConsistentOut::levelAdds, SpGistSearchItem::recheck, SpGistSearchItem::recheckDistances, spgInnerConsistentOut::reconstructedValues, spgAllocSearchItem(), IndexTupleData::t_tid, SpGistSearchItem::traversalValue, spgInnerConsistentOut::traversalValues, and SpGistSearchItem::value.

Referenced by spgInnerTest().

◆ spgNewHeapItem()

static SpGistSearchItem * spgNewHeapItem ( SpGistScanOpaque  so,
int  level,
SpGistLeafTuple  leafTuple,
Datum  leafValue,
bool  recheck,
bool  recheckDistances,
bool  isnull,
double distances 
)
static

Definition at line 458 of file spgscan.c.

461{
462 SpGistSearchItem *item = spgAllocSearchItem(so, isnull, distances);
463
464 item->level = level;
465 item->heapPtr = leafTuple->heapPtr;
466
467 /*
468 * If we need the reconstructed value, copy it to queue cxt out of tmp
469 * cxt. Caution: the leaf_consistent method may not have supplied a value
470 * if we didn't ask it to, and mildly-broken methods might supply one of
471 * the wrong type. The correct leafValue type is attType not leafType.
472 */
473 if (so->want_itup)
474 {
475 item->value = isnull ? (Datum) 0 :
476 datumCopy(leafValue, so->state.attType.attbyval,
477 so->state.attType.attlen);
478
479 /*
480 * If we're going to need to reconstruct INCLUDE attributes, store the
481 * whole leaf tuple so we can get the INCLUDE attributes out of it.
482 */
483 if (so->state.leafTupDesc->natts > 1)
484 {
485 item->leafTuple = palloc(leafTuple->size);
486 memcpy(item->leafTuple, leafTuple, leafTuple->size);
487 }
488 else
489 item->leafTuple = NULL;
490 }
491 else
492 {
493 item->value = (Datum) 0;
494 item->leafTuple = NULL;
495 }
496 item->traversalValue = NULL;
497 item->isLeaf = true;
498 item->recheck = recheck;
499 item->recheckDistances = recheckDistances;
500
501 return item;
502}
int16 attlen

References datumCopy(), fb(), SpGistSearchItem::heapPtr, SpGistLeafTupleData::heapPtr, SpGistSearchItem::isLeaf, SpGistSearchItem::leafTuple, SpGistSearchItem::level, palloc(), SpGistSearchItem::recheck, SpGistSearchItem::recheckDistances, SpGistLeafTupleData::size, spgAllocSearchItem(), SpGistSearchItem::traversalValue, and SpGistSearchItem::value.

Referenced by spgLeafTest().

◆ spgPrepareScanKeys()

static void spgPrepareScanKeys ( IndexScanDesc  scan)
static

Definition at line 209 of file spgscan.c.

210{
212 bool qual_ok;
213 bool haveIsNull;
214 bool haveNotNull;
215 int nkeys;
216 int i;
217
218 so->numberOfOrderBys = scan->numberOfOrderBys;
219 so->orderByData = scan->orderByData;
220
221 if (so->numberOfOrderBys <= 0)
222 so->numberOfNonNullOrderBys = 0;
223 else
224 {
225 int j = 0;
226
227 /*
228 * Remove all NULL keys, but remember their offsets in the original
229 * array.
230 */
231 for (i = 0; i < scan->numberOfOrderBys; i++)
232 {
233 ScanKey skey = &so->orderByData[i];
234
235 if (skey->sk_flags & SK_ISNULL)
236 so->nonNullOrderByOffsets[i] = -1;
237 else
238 {
239 if (i != j)
240 so->orderByData[j] = *skey;
241
242 so->nonNullOrderByOffsets[i] = j++;
243 }
244 }
245
246 so->numberOfNonNullOrderBys = j;
247 }
248
249 if (scan->numberOfKeys <= 0)
250 {
251 /* If no quals, whole-index scan is required */
252 so->searchNulls = true;
253 so->searchNonNulls = true;
254 so->numberOfKeys = 0;
255 return;
256 }
257
258 /* Examine the given quals */
259 qual_ok = true;
260 haveIsNull = haveNotNull = false;
261 nkeys = 0;
262 for (i = 0; i < scan->numberOfKeys; i++)
263 {
264 ScanKey skey = &scan->keyData[i];
265
266 if (skey->sk_flags & SK_SEARCHNULL)
267 haveIsNull = true;
268 else if (skey->sk_flags & SK_SEARCHNOTNULL)
269 haveNotNull = true;
270 else if (skey->sk_flags & SK_ISNULL)
271 {
272 /* ordinary qual with null argument - unsatisfiable */
273 qual_ok = false;
274 break;
275 }
276 else
277 {
278 /* ordinary qual, propagate into so->keyData */
279 so->keyData[nkeys++] = *skey;
280 /* this effectively creates a not-null requirement */
281 haveNotNull = true;
282 }
283 }
284
285 /* IS NULL in combination with something else is unsatisfiable */
286 if (haveIsNull && haveNotNull)
287 qual_ok = false;
288
289 /* Emit results */
290 if (qual_ok)
291 {
292 so->searchNulls = haveIsNull;
293 so->searchNonNulls = haveNotNull;
294 so->numberOfKeys = nkeys;
295 }
296 else
297 {
298 so->searchNulls = false;
299 so->searchNonNulls = false;
300 so->numberOfKeys = 0;
301 }
302}
int j
Definition isn.c:78
#define SK_SEARCHNOTNULL
Definition skey.h:122
#define SK_SEARCHNULL
Definition skey.h:121
#define SK_ISNULL
Definition skey.h:115
struct ScanKeyData * keyData
Definition relscan.h:142
struct ScanKeyData * orderByData
Definition relscan.h:143

References fb(), i, j, IndexScanDescData::keyData, IndexScanDescData::numberOfKeys, IndexScanDescData::numberOfOrderBys, IndexScanDescData::opaque, IndexScanDescData::orderByData, SK_ISNULL, SK_SEARCHNOTNULL, and SK_SEARCHNULL.

Referenced by spgrescan().

◆ spgrescan()

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

Definition at line 375 of file spgscan.c.

377{
379
380 /* copy scankeys into local storage */
381 if (scankey && scan->numberOfKeys > 0)
382 memcpy(scan->keyData, scankey, scan->numberOfKeys * sizeof(ScanKeyData));
383
384 /* initialize order-by data if needed */
385 if (orderbys && scan->numberOfOrderBys > 0)
386 {
387 int i;
388
389 memcpy(scan->orderByData, orderbys, scan->numberOfOrderBys * sizeof(ScanKeyData));
390
391 for (i = 0; i < scan->numberOfOrderBys; i++)
392 {
393 ScanKey skey = &scan->orderByData[i];
394
395 /*
396 * Look up the datatype returned by the original ordering
397 * operator. SP-GiST always uses a float8 for the distance
398 * function, but the ordering operator could be anything else.
399 *
400 * XXX: The distance function is only allowed to be lossy if the
401 * ordering operator's result type is float4 or float8. Otherwise
402 * we don't know how to return the distance to the executor. But
403 * we cannot check that here, as we won't know if the distance
404 * function is lossy until it returns *recheck = true for the
405 * first time.
406 */
407 so->orderByTypes[i] = get_func_rettype(skey->sk_func.fn_oid);
408 }
409 }
410
411 /* preprocess scankeys, set up the representation in *so */
412 spgPrepareScanKeys(scan);
413
414 /* set up starting queue entries */
416
417 /* count an indexscan for stats */
419 if (scan->instrument)
420 scan->instrument->nsearches++;
421}
Oid get_func_rettype(Oid funcid)
Definition lsyscache.c:1805
#define pgstat_count_index_scan(rel)
Definition pgstat.h:705
static void resetSpGistScanOpaque(SpGistScanOpaque so)
Definition spgscan.c:155
static void spgPrepareScanKeys(IndexScanDesc scan)
Definition spgscan.c:209
struct IndexScanInstrumentation * instrument
Definition relscan.h:160

References fb(), get_func_rettype(), i, IndexScanDescData::indexRelation, IndexScanDescData::instrument, IndexScanDescData::keyData, IndexScanInstrumentation::nsearches, IndexScanDescData::numberOfKeys, IndexScanDescData::numberOfOrderBys, IndexScanDescData::opaque, IndexScanDescData::orderByData, pgstat_count_index_scan, resetSpGistScanOpaque(), and spgPrepareScanKeys().

Referenced by spghandler().

◆ spgTestLeafTuple()

static OffsetNumber spgTestLeafTuple ( SpGistScanOpaque  so,
SpGistSearchItem item,
Page  page,
OffsetNumber  offset,
bool  isnull,
bool  isroot,
bool reportedSome,
storeRes_func  storeRes 
)
static

Definition at line 758 of file spgscan.c.

764{
765 SpGistLeafTuple leafTuple = (SpGistLeafTuple)
766 PageGetItem(page, PageGetItemId(page, offset));
767
768 if (leafTuple->tupstate != SPGIST_LIVE)
769 {
770 if (!isroot) /* all tuples on root should be live */
771 {
772 if (leafTuple->tupstate == SPGIST_REDIRECT)
773 {
774 /* redirection tuple should be first in chain */
775 Assert(offset == ItemPointerGetOffsetNumber(&item->heapPtr));
776 /* transfer attention to redirect point */
777 item->heapPtr = ((SpGistDeadTuple) leafTuple)->pointer;
780 }
781
782 if (leafTuple->tupstate == SPGIST_DEAD)
783 {
784 /* dead tuple should be first in chain */
785 Assert(offset == ItemPointerGetOffsetNumber(&item->heapPtr));
786 /* No live entries on this page */
789 }
790 }
791
792 /* We should not arrive at a placeholder */
793 elog(ERROR, "unexpected SPGiST tuple state: %d", leafTuple->tupstate);
795 }
796
797 Assert(ItemPointerIsValid(&leafTuple->heapPtr));
798
799 spgLeafTest(so, item, leafTuple, isnull, reportedSome, storeRes);
800
801 return SGLT_GET_NEXTOFFSET(leafTuple);
802}
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
Definition bufpage.h:243
static void * PageGetItem(PageData *page, const ItemIdData *itemId)
Definition bufpage.h:353
static OffsetNumber ItemPointerGetOffsetNumber(const ItemPointerData *pointer)
Definition itemptr.h:124
static BlockNumber ItemPointerGetBlockNumber(const ItemPointerData *pointer)
Definition itemptr.h:103
SpGistDeadTupleData * SpGistDeadTuple
#define SPGIST_REDIRECT
#define SPGIST_LIVE
#define SGLT_GET_NEXTOFFSET(spgLeafTuple)
#define SPGIST_DEAD
#define SPGIST_METAPAGE_BLKNO
struct SpGistLeafTupleData * SpGistLeafTuple
static bool spgLeafTest(SpGistScanOpaque so, SpGistSearchItem *item, SpGistLeafTuple leafTuple, bool isnull, bool *reportedSome, storeRes_func storeRes)
Definition spgscan.c:511

References Assert, elog, ERROR, fb(), SpGistSearchItem::heapPtr, SpGistLeafTupleData::heapPtr, InvalidOffsetNumber, ItemPointerGetBlockNumber(), ItemPointerGetOffsetNumber(), ItemPointerIsValid(), PageGetItem(), PageGetItemId(), SGLT_GET_NEXTOFFSET, SPGIST_DEAD, SPGIST_LIVE, SPGIST_METAPAGE_BLKNO, SPGIST_REDIRECT, SpGistBreakOffsetNumber, SpGistErrorOffsetNumber, SpGistRedirectOffsetNumber, spgLeafTest(), and SpGistLeafTupleData::tupstate.

Referenced by spgWalk().

◆ spgWalk()

static void spgWalk ( Relation  index,
SpGistScanOpaque  so,
bool  scanWholeIndex,
storeRes_func  storeRes 
)
static

Definition at line 812 of file spgscan.c.

814{
815 Buffer buffer = InvalidBuffer;
816 bool reportedSome = false;
817
818 while (scanWholeIndex || !reportedSome)
819 {
821
822 if (item == NULL)
823 break; /* No more items in queue -> done */
824
826 /* Check for interrupts, just in case of infinite loop */
828
829 if (item->isLeaf)
830 {
831 /* We store heap items in the queue only in case of ordered search */
832 Assert(so->numberOfNonNullOrderBys > 0);
833 storeRes(so, &item->heapPtr, item->value, item->isNull,
834 item->leafTuple, item->recheck,
835 item->recheckDistances, item->distances);
836 reportedSome = true;
837 }
838 else
839 {
842 Page page;
843 bool isnull;
844
845 if (buffer == InvalidBuffer)
846 {
847 buffer = ReadBuffer(index, blkno);
849 }
850 else if (blkno != BufferGetBlockNumber(buffer))
851 {
852 UnlockReleaseBuffer(buffer);
853 buffer = ReadBuffer(index, blkno);
855 }
856
857 /* else new pointer points to the same page, no work needed */
858
859 page = BufferGetPage(buffer);
860
861 isnull = SpGistPageStoresNulls(page) ? true : false;
862
863 if (SpGistPageIsLeaf(page))
864 {
865 /* Page is a leaf - that is, all its tuples are heap items */
867
868 if (SpGistBlockIsRoot(blkno))
869 {
870 /* When root is a leaf, examine all its tuples */
871 for (offset = FirstOffsetNumber; offset <= max; offset++)
872 (void) spgTestLeafTuple(so, item, page, offset,
873 isnull, true,
875 }
876 else
877 {
878 /* Normal case: just examine the chain we arrived at */
879 while (offset != InvalidOffsetNumber)
880 {
881 Assert(offset >= FirstOffsetNumber && offset <= max);
882 offset = spgTestLeafTuple(so, item, page, offset,
883 isnull, false,
885 if (offset == SpGistRedirectOffsetNumber)
886 goto redirect;
887 }
888 }
889 }
890 else /* page is inner */
891 {
893 PageGetItem(page, PageGetItemId(page, offset));
894
895 if (innerTuple->tupstate != SPGIST_LIVE)
896 {
897 if (innerTuple->tupstate == SPGIST_REDIRECT)
898 {
899 /* transfer attention to redirect point */
900 item->heapPtr = ((SpGistDeadTuple) innerTuple)->pointer;
903 goto redirect;
904 }
905 elog(ERROR, "unexpected SPGiST tuple state: %d",
906 innerTuple->tupstate);
907 }
908
909 spgInnerTest(so, item, innerTuple, isnull);
910 }
911 }
912
913 /* done with this scan item */
914 spgFreeSearchItem(so, item);
915 /* clear temp context before proceeding to the next one */
916 MemoryContextReset(so->tempCxt);
917 }
918
919 if (buffer != InvalidBuffer)
920 UnlockReleaseBuffer(buffer);
921}
uint32 BlockNumber
Definition block.h:31
int Buffer
Definition buf.h:23
#define InvalidBuffer
Definition buf.h:25
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition bufmgr.c:4356
void UnlockReleaseBuffer(Buffer buffer)
Definition bufmgr.c:5518
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition bufmgr.c:864
static Page BufferGetPage(Buffer buffer)
Definition bufmgr.h:466
@ BUFFER_LOCK_SHARE
Definition bufmgr.h:210
static void LockBuffer(Buffer buffer, BufferLockMode mode)
Definition bufmgr.h:328
PageData * Page
Definition bufpage.h:81
static OffsetNumber PageGetMaxOffsetNumber(const PageData *page)
Definition bufpage.h:371
return true
Definition isn.c:130
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:123
uint16 OffsetNumber
Definition off.h:24
SpGistInnerTupleData * SpGistInnerTuple
#define SpGistPageStoresNulls(page)
#define SpGistPageIsLeaf(page)
#define SpGistBlockIsRoot(blkno)
static SpGistSearchItem * spgGetNextQueueItem(SpGistScanOpaque so)
Definition spgscan.c:741
static OffsetNumber spgTestLeafTuple(SpGistScanOpaque so, SpGistSearchItem *item, Page page, OffsetNumber offset, bool isnull, bool isroot, bool *reportedSome, storeRes_func storeRes)
Definition spgscan.c:758
static void spgFreeSearchItem(SpGistScanOpaque so, SpGistSearchItem *item)
Definition spgscan.c:85
static void spgInnerTest(SpGistScanOpaque so, SpGistSearchItem *item, SpGistInnerTuple innerTuple, bool isnull)
Definition spgscan.c:662

References Assert, BUFFER_LOCK_SHARE, BufferGetBlockNumber(), BufferGetPage(), CHECK_FOR_INTERRUPTS, SpGistSearchItem::distances, elog, ERROR, fb(), FirstOffsetNumber, SpGistSearchItem::heapPtr, InvalidBuffer, InvalidOffsetNumber, SpGistSearchItem::isLeaf, SpGistSearchItem::isNull, ItemPointerGetBlockNumber(), ItemPointerGetOffsetNumber(), SpGistSearchItem::leafTuple, LockBuffer(), MemoryContextReset(), PageGetItem(), PageGetItemId(), PageGetMaxOffsetNumber(), ReadBuffer(), SpGistSearchItem::recheck, SpGistSearchItem::recheckDistances, spgFreeSearchItem(), spgGetNextQueueItem(), spgInnerTest(), SPGIST_LIVE, SPGIST_METAPAGE_BLKNO, SPGIST_REDIRECT, SpGistBlockIsRoot, SpGistPageIsLeaf, SpGistPageStoresNulls, SpGistRedirectOffsetNumber, spgTestLeafTuple(), true, UnlockReleaseBuffer(), and SpGistSearchItem::value.

Referenced by spggetbitmap(), and spggettuple().

◆ storeBitmap()

static void storeBitmap ( SpGistScanOpaque  so,
ItemPointer  heapPtr,
Datum  leafValue,
bool  isnull,
SpGistLeafTuple  leafTuple,
bool  recheck,
bool  recheckDistances,
double distances 
)
static

Definition at line 926 of file spgscan.c.

930{
931 Assert(!recheckDistances && !distances);
932 tbm_add_tuples(so->tbm, heapPtr, 1, recheck);
933 so->ntids++;
934}
void tbm_add_tuples(TIDBitmap *tbm, const ItemPointerData *tids, int ntids, bool recheck)
Definition tidbitmap.c:367

References Assert, fb(), and tbm_add_tuples().

Referenced by spggetbitmap().

◆ storeGettuple()

static void storeGettuple ( SpGistScanOpaque  so,
ItemPointer  heapPtr,
Datum  leafValue,
bool  isnull,
SpGistLeafTuple  leafTuple,
bool  recheck,
bool  recheckDistances,
double nonNullDistances 
)
static

Definition at line 954 of file spgscan.c.

958{
960 so->heapPtrs[so->nPtrs] = *heapPtr;
961 so->recheck[so->nPtrs] = recheck;
962 so->recheckDistances[so->nPtrs] = recheckDistances;
963
964 if (so->numberOfOrderBys > 0)
965 {
966 if (isnull || so->numberOfNonNullOrderBys <= 0)
967 so->distances[so->nPtrs] = NULL;
968 else
969 {
971 so->numberOfOrderBys);
972 int i;
973
974 for (i = 0; i < so->numberOfOrderBys; i++)
975 {
976 int offset = so->nonNullOrderByOffsets[i];
977
978 if (offset >= 0)
979 {
980 /* Copy non-NULL distance value */
981 distances[i].value = nonNullDistances[offset];
982 distances[i].isnull = false;
983 }
984 else
985 {
986 /* Set distance's NULL flag. */
987 distances[i].value = 0.0;
988 distances[i].isnull = true;
989 }
990 }
991
992 so->distances[so->nPtrs] = distances;
993 }
994 }
995
996 if (so->want_itup)
997 {
998 /*
999 * Reconstruct index data. We have to copy the datum out of the temp
1000 * context anyway, so we may as well create the tuple here.
1001 */
1004
1005 /* We only need to deform the old tuple if it has INCLUDE attributes */
1006 if (so->state.leafTupDesc->natts > 1)
1007 spgDeformLeafTuple(leafTuple, so->state.leafTupDesc,
1008 leafDatums, leafIsnulls, isnull);
1009
1010 leafDatums[spgKeyColumn] = leafValue;
1011 leafIsnulls[spgKeyColumn] = isnull;
1012
1013 so->reconTups[so->nPtrs] = heap_form_tuple(so->reconTupDesc,
1014 leafDatums,
1015 leafIsnulls);
1016 }
1017 so->nPtrs++;
1018}
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition heaptuple.c:1117
#define MaxIndexTuplesPerPage
Definition itup.h:181
#define INDEX_MAX_KEYS
#define spgKeyColumn
void spgDeformLeafTuple(SpGistLeafTuple tup, TupleDesc tupleDescriptor, Datum *datums, bool *isnulls, bool keyColumnIsNull)
Definition spgutils.c:1116

References Assert, fb(), heap_form_tuple(), i, INDEX_MAX_KEYS, IndexOrderByDistance::isnull, MaxIndexTuplesPerPage, palloc_array, spgDeformLeafTuple(), spgKeyColumn, and IndexOrderByDistance::value.

Referenced by spggettuple().