#include "postgres.h"
#include "access/relscan.h"
#include "access/spgist_private.h"
#include "miscadmin.h"
#include "storage/bufmgr.h"
#include "utils/datum.h"
#include "utils/memutils.h"
#include "utils/rel.h"
Go to the source code of this file.
Data Structures | |
struct | ScanStackEntry |
Typedefs | |
typedef void(* | storeRes_func )(SpGistScanOpaque so, ItemPointer heapPtr, Datum leafValue, bool isnull, bool recheck) |
typedef struct ScanStackEntry | ScanStackEntry |
Functions | |
static void | freeScanStackEntry (SpGistScanOpaque so, ScanStackEntry *stackEntry) |
static void | freeScanStack (SpGistScanOpaque so) |
static void | resetSpGistScanOpaque (SpGistScanOpaque so) |
static void | spgPrepareScanKeys (IndexScanDesc scan) |
Datum | spgbeginscan (PG_FUNCTION_ARGS) |
Datum | spgrescan (PG_FUNCTION_ARGS) |
Datum | spgendscan (PG_FUNCTION_ARGS) |
Datum | spgmarkpos (PG_FUNCTION_ARGS) |
Datum | spgrestrpos (PG_FUNCTION_ARGS) |
static bool | spgLeafTest (Relation index, SpGistScanOpaque so, SpGistLeafTuple leafTuple, bool isnull, int level, Datum reconstructedValue, Datum *leafValue, bool *recheck) |
static void | spgWalk (Relation index, SpGistScanOpaque so, bool scanWholeIndex, storeRes_func storeRes) |
static void | storeBitmap (SpGistScanOpaque so, ItemPointer heapPtr, Datum leafValue, bool isnull, bool recheck) |
Datum | spggetbitmap (PG_FUNCTION_ARGS) |
static void | storeGettuple (SpGistScanOpaque so, ItemPointer heapPtr, Datum leafValue, bool isnull, bool recheck) |
Datum | spggettuple (PG_FUNCTION_ARGS) |
Datum | spgcanreturn (PG_FUNCTION_ARGS) |
typedef struct ScanStackEntry ScanStackEntry |
typedef void(* storeRes_func)(SpGistScanOpaque so, ItemPointer heapPtr, Datum leafValue, bool isnull, bool recheck) |
static void freeScanStack | ( | SpGistScanOpaque | so | ) | [static] |
Definition at line 50 of file spgscan.c.
References freeScanStackEntry(), lfirst, list_free(), and SpGistScanOpaqueData::scanStack.
Referenced by resetSpGistScanOpaque().
{ ListCell *lc; foreach(lc, so->scanStack) { freeScanStackEntry(so, (ScanStackEntry *) lfirst(lc)); } list_free(so->scanStack); so->scanStack = NIL; }
static void freeScanStackEntry | ( | SpGistScanOpaque | so, | |
ScanStackEntry * | stackEntry | |||
) | [static] |
Definition at line 40 of file spgscan.c.
References SpGistTypeDesc::attbyval, SpGistState::attType, DatumGetPointer, NULL, pfree(), ScanStackEntry::reconstructedValue, and SpGistScanOpaqueData::state.
Referenced by freeScanStack(), and spgWalk().
{ if (!so->state.attType.attbyval && DatumGetPointer(stackEntry->reconstructedValue) != NULL) pfree(DatumGetPointer(stackEntry->reconstructedValue)); pfree(stackEntry); }
static void resetSpGistScanOpaque | ( | SpGistScanOpaque | so | ) | [static] |
Definition at line 67 of file spgscan.c.
References FirstOffsetNumber, freeScanStack(), i, SpGistScanOpaqueData::indexTups, SpGistScanOpaqueData::iPtr, ItemPointerSet, lappend(), SpGistScanOpaqueData::nPtrs, palloc0(), pfree(), ScanStackEntry::ptr, SpGistScanOpaqueData::scanStack, SpGistScanOpaqueData::searchNonNulls, SpGistScanOpaqueData::searchNulls, SPGIST_NULL_BLKNO, SPGIST_ROOT_BLKNO, and SpGistScanOpaqueData::want_itup.
Referenced by spgrescan().
{ ScanStackEntry *startEntry; freeScanStack(so); if (so->searchNulls) { /* Stack a work item to scan the null index entries */ startEntry = (ScanStackEntry *) palloc0(sizeof(ScanStackEntry)); ItemPointerSet(&startEntry->ptr, SPGIST_NULL_BLKNO, FirstOffsetNumber); so->scanStack = lappend(so->scanStack, startEntry); } if (so->searchNonNulls) { /* Stack a work item to scan the non-null index entries */ startEntry = (ScanStackEntry *) palloc0(sizeof(ScanStackEntry)); ItemPointerSet(&startEntry->ptr, SPGIST_ROOT_BLKNO, FirstOffsetNumber); so->scanStack = lappend(so->scanStack, startEntry); } if (so->want_itup) { /* Must pfree IndexTuples to avoid memory leak */ int i; for (i = 0; i < so->nPtrs; i++) pfree(so->indexTups[i]); } so->iPtr = so->nPtrs = 0; }
Datum spgbeginscan | ( | PG_FUNCTION_ARGS | ) |
Definition at line 177 of file spgscan.c.
References ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, ALLOCSET_DEFAULT_MINSIZE, AllocSetContextCreate(), CurrentMemoryContext, IndexScanDescData::indexRelation, SpGistScanOpaqueData::indexTupDesc, initSpGistState(), SpGistScanOpaqueData::keyData, IndexScanDescData::opaque, palloc(), palloc0(), PG_GETARG_INT32, PG_GETARG_POINTER, PG_RETURN_POINTER, RelationGetDescr, RelationGetIndexScan(), SpGistScanOpaqueData::state, SpGistScanOpaqueData::tempCxt, and IndexScanDescData::xs_itupdesc.
{ Relation rel = (Relation) PG_GETARG_POINTER(0); int keysz = PG_GETARG_INT32(1); /* ScanKey scankey = (ScanKey) PG_GETARG_POINTER(2); */ IndexScanDesc scan; SpGistScanOpaque so; scan = RelationGetIndexScan(rel, keysz, 0); so = (SpGistScanOpaque) palloc0(sizeof(SpGistScanOpaqueData)); if (keysz > 0) so->keyData = (ScanKey) palloc(sizeof(ScanKeyData) * keysz); else so->keyData = NULL; initSpGistState(&so->state, scan->indexRelation); so->tempCxt = AllocSetContextCreate(CurrentMemoryContext, "SP-GiST search temporary context", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); /* Set up indexTupDesc and xs_itupdesc in case it's an index-only scan */ so->indexTupDesc = scan->xs_itupdesc = RelationGetDescr(rel); scan->opaque = so; PG_RETURN_POINTER(scan); }
Datum spgcanreturn | ( | PG_FUNCTION_ARGS | ) |
Definition at line 658 of file spgscan.c.
References spgConfigOut::canReturnData, SpGistCache::config, PG_GETARG_POINTER, PG_RETURN_BOOL, and spgGetCache().
{ Relation index = (Relation) PG_GETARG_POINTER(0); SpGistCache *cache; /* We can do it if the opclass config function says so */ cache = spgGetCache(index); PG_RETURN_BOOL(cache->config.canReturnData); }
Datum spgendscan | ( | PG_FUNCTION_ARGS | ) |
Definition at line 232 of file spgscan.c.
References MemoryContextDelete(), IndexScanDescData::opaque, PG_GETARG_POINTER, PG_RETURN_VOID, and SpGistScanOpaqueData::tempCxt.
{ IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0); SpGistScanOpaque so = (SpGistScanOpaque) scan->opaque; MemoryContextDelete(so->tempCxt); PG_RETURN_VOID(); }
Datum spggetbitmap | ( | PG_FUNCTION_ARGS | ) |
Definition at line 575 of file spgscan.c.
References IndexScanDescData::indexRelation, SpGistScanOpaqueData::ntids, IndexScanDescData::opaque, PG_GETARG_POINTER, PG_RETURN_INT64, spgWalk(), storeBitmap(), SpGistScanOpaqueData::tbm, and SpGistScanOpaqueData::want_itup.
{ IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0); TIDBitmap *tbm = (TIDBitmap *) PG_GETARG_POINTER(1); SpGistScanOpaque so = (SpGistScanOpaque) scan->opaque; /* Copy want_itup to *so so we don't need to pass it around separately */ so->want_itup = false; so->tbm = tbm; so->ntids = 0; spgWalk(scan->indexRelation, so, true, storeBitmap); PG_RETURN_INT64(so->ntids); }
Datum spggettuple | ( | PG_FUNCTION_ARGS | ) |
Definition at line 614 of file spgscan.c.
References elog, ERROR, ForwardScanDirection, SpGistScanOpaqueData::heapPtrs, i, IndexScanDescData::indexRelation, SpGistScanOpaqueData::indexTups, SpGistScanOpaqueData::iPtr, SpGistScanOpaqueData::nPtrs, IndexScanDescData::opaque, pfree(), PG_GETARG_INT32, PG_GETARG_POINTER, PG_RETURN_BOOL, SpGistScanOpaqueData::recheck, spgWalk(), storeGettuple(), HeapTupleData::t_self, SpGistScanOpaqueData::want_itup, IndexScanDescData::xs_ctup, IndexScanDescData::xs_itup, IndexScanDescData::xs_recheck, and IndexScanDescData::xs_want_itup.
{ IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0); ScanDirection dir = (ScanDirection) PG_GETARG_INT32(1); SpGistScanOpaque so = (SpGistScanOpaque) scan->opaque; if (dir != ForwardScanDirection) elog(ERROR, "SP-GiST only supports forward scan direction"); /* Copy want_itup to *so so we don't need to pass it around separately */ so->want_itup = scan->xs_want_itup; for (;;) { if (so->iPtr < so->nPtrs) { /* continuing to return tuples from a leaf page */ scan->xs_ctup.t_self = so->heapPtrs[so->iPtr]; scan->xs_recheck = so->recheck[so->iPtr]; scan->xs_itup = so->indexTups[so->iPtr]; so->iPtr++; PG_RETURN_BOOL(true); } if (so->want_itup) { /* Must pfree IndexTuples to avoid memory leak */ int i; for (i = 0; i < so->nPtrs; i++) pfree(so->indexTups[i]); } so->iPtr = so->nPtrs = 0; spgWalk(scan->indexRelation, so, false, storeGettuple); if (so->nPtrs == 0) break; /* must have completed scan */ } PG_RETURN_BOOL(false); }
static bool spgLeafTest | ( | Relation | index, | |
SpGistScanOpaque | so, | |||
SpGistLeafTuple | leafTuple, | |||
bool | isnull, | |||
int | level, | |||
Datum | reconstructedValue, | |||
Datum * | leafValue, | |||
bool * | recheck | |||
) | [static] |
Definition at line 263 of file spgscan.c.
References Assert, DatumGetBool, FunctionCall2Coll(), index_getprocinfo(), SpGistScanOpaqueData::keyData, spgLeafConsistentIn::leafDatum, spgLeafConsistentOut::leafValue, spgLeafConsistentIn::level, MemoryContextSwitchTo(), spgLeafConsistentIn::nkeys, SpGistScanOpaqueData::numberOfKeys, PointerGetDatum, RelationData::rd_indcollation, spgLeafConsistentOut::recheck, spgLeafConsistentIn::reconstructedValue, spgLeafConsistentIn::returnData, spgLeafConsistentIn::scankeys, SpGistScanOpaqueData::searchNulls, SGLTDATUM, SPGIST_LEAF_CONSISTENT_PROC, SpGistScanOpaqueData::state, SpGistScanOpaqueData::tempCxt, and SpGistScanOpaqueData::want_itup.
Referenced by spgWalk().
{ bool result; Datum leafDatum; spgLeafConsistentIn in; spgLeafConsistentOut out; FmgrInfo *procinfo; MemoryContext oldCtx; if (isnull) { /* Should not have arrived on a nulls page unless nulls are wanted */ Assert(so->searchNulls); *leafValue = (Datum) 0; *recheck = false; return true; } leafDatum = SGLTDATUM(leafTuple, &so->state); /* use temp context for calling leaf_consistent */ oldCtx = MemoryContextSwitchTo(so->tempCxt); in.scankeys = so->keyData; in.nkeys = so->numberOfKeys; in.reconstructedValue = reconstructedValue; in.level = level; in.returnData = so->want_itup; in.leafDatum = leafDatum; out.leafValue = (Datum) 0; out.recheck = false; procinfo = index_getprocinfo(index, 1, SPGIST_LEAF_CONSISTENT_PROC); result = DatumGetBool(FunctionCall2Coll(procinfo, index->rd_indcollation[0], PointerGetDatum(&in), PointerGetDatum(&out))); *leafValue = out.leafValue; *recheck = out.recheck; MemoryContextSwitchTo(oldCtx); return result; }
Datum spgmarkpos | ( | PG_FUNCTION_ARGS | ) |
Definition at line 243 of file spgscan.c.
References elog, ERROR, and PG_RETURN_VOID.
{ elog(ERROR, "SPGiST does not support mark/restore"); PG_RETURN_VOID(); }
static void spgPrepareScanKeys | ( | IndexScanDesc | scan | ) | [static] |
Definition at line 112 of file spgscan.c.
References i, SpGistScanOpaqueData::keyData, IndexScanDescData::keyData, SpGistScanOpaqueData::numberOfKeys, IndexScanDescData::numberOfKeys, IndexScanDescData::opaque, SpGistScanOpaqueData::searchNonNulls, SpGistScanOpaqueData::searchNulls, ScanKeyData::sk_flags, SK_ISNULL, SK_SEARCHNOTNULL, and SK_SEARCHNULL.
Referenced by spgrescan().
{ SpGistScanOpaque so = (SpGistScanOpaque) scan->opaque; bool qual_ok; bool haveIsNull; bool haveNotNull; int nkeys; int i; if (scan->numberOfKeys <= 0) { /* If no quals, whole-index scan is required */ so->searchNulls = true; so->searchNonNulls = true; so->numberOfKeys = 0; return; } /* Examine the given quals */ qual_ok = true; haveIsNull = haveNotNull = false; nkeys = 0; for (i = 0; i < scan->numberOfKeys; i++) { ScanKey skey = &scan->keyData[i]; if (skey->sk_flags & SK_SEARCHNULL) haveIsNull = true; else if (skey->sk_flags & SK_SEARCHNOTNULL) haveNotNull = true; else if (skey->sk_flags & SK_ISNULL) { /* ordinary qual with null argument - unsatisfiable */ qual_ok = false; break; } else { /* ordinary qual, propagate into so->keyData */ so->keyData[nkeys++] = *skey; /* this effectively creates a not-null requirement */ haveNotNull = true; } } /* IS NULL in combination with something else is unsatisfiable */ if (haveIsNull && haveNotNull) qual_ok = false; /* Emit results */ if (qual_ok) { so->searchNulls = haveIsNull; so->searchNonNulls = haveNotNull; so->numberOfKeys = nkeys; } else { so->searchNulls = false; so->searchNonNulls = false; so->numberOfKeys = 0; } }
Datum spgrescan | ( | PG_FUNCTION_ARGS | ) |
Definition at line 209 of file spgscan.c.
References IndexScanDescData::keyData, memmove, IndexScanDescData::numberOfKeys, IndexScanDescData::opaque, PG_GETARG_POINTER, PG_RETURN_VOID, resetSpGistScanOpaque(), and spgPrepareScanKeys().
{ IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0); SpGistScanOpaque so = (SpGistScanOpaque) scan->opaque; ScanKey scankey = (ScanKey) PG_GETARG_POINTER(1); /* copy scankeys into local storage */ if (scankey && scan->numberOfKeys > 0) { memmove(scan->keyData, scankey, scan->numberOfKeys * sizeof(ScanKeyData)); } /* preprocess scankeys, set up the representation in *so */ spgPrepareScanKeys(scan); /* set up starting stack entries */ resetSpGistScanOpaque(so); PG_RETURN_VOID(); }
Datum spgrestrpos | ( | PG_FUNCTION_ARGS | ) |
Definition at line 250 of file spgscan.c.
References elog, ERROR, and PG_RETURN_VOID.
{ elog(ERROR, "SPGiST does not support mark/restore"); PG_RETURN_VOID(); }
static void spgWalk | ( | Relation | index, | |
SpGistScanOpaque | so, | |||
bool | scanWholeIndex, | |||
storeRes_func | storeRes | |||
) | [static] |
Definition at line 321 of file spgscan.c.
References SpGistInnerTupleData::allTheSame, spgInnerConsistentIn::allTheSame, Assert, SpGistTypeDesc::attbyval, SpGistTypeDesc::attlen, SpGistState::attType, BUFFER_LOCK_SHARE, BufferGetBlockNumber(), BufferGetPage, CHECK_FOR_INTERRUPTS, datumCopy(), elog, ERROR, FirstOffsetNumber, freeScanStackEntry(), FunctionCall2Coll(), spgInnerConsistentIn::hasPrefix, SpGistLeafTupleData::heapPtr, i, index_getprocinfo(), InvalidBuffer, InvalidOffsetNumber, ItemPointerGetBlockNumber, ItemPointerGetOffsetNumber, ItemPointerIsValid, SpGistScanOpaqueData::keyData, lcons(), spgInnerConsistentIn::level, ScanStackEntry::level, spgInnerConsistentOut::levelAdds, linitial, list_delete_first(), LockBuffer(), MemoryContextReset(), MemoryContextSwitchTo(), SpGistLeafTupleData::nextOffset, NIL, spgInnerConsistentIn::nkeys, spgInnerConsistentOut::nNodes, SpGistInnerTupleData::nNodes, spgInnerConsistentIn::nNodes, spgInnerConsistentIn::nodeLabels, spgInnerConsistentOut::nodeNumbers, SpGistScanOpaqueData::numberOfKeys, PageGetItem, PageGetItemId, PageGetMaxOffsetNumber, palloc(), PointerGetDatum, spgInnerConsistentIn::prefixDatum, SpGistInnerTupleData::prefixSize, ScanStackEntry::ptr, RelationData::rd_indcollation, ReadBuffer(), spgInnerConsistentIn::reconstructedValue, ScanStackEntry::reconstructedValue, spgInnerConsistentOut::reconstructedValues, spgInnerConsistentIn::returnData, spgInnerConsistentIn::scankeys, SpGistScanOpaqueData::scanStack, SGITDATUM, SGITITERATE, spgExtractNodeLabels(), SPGIST_DEAD, SPGIST_INNER_CONSISTENT_PROC, SPGIST_LIVE, SPGIST_METAPAGE_BLKNO, SPGIST_REDIRECT, SpGistBlockIsRoot, SpGistPageIsLeaf, SpGistPageStoresNulls, spgLeafTest(), SpGistScanOpaqueData::state, IndexTupleData::t_tid, SpGistScanOpaqueData::tempCxt, SpGistInnerTupleData::tupstate, SpGistLeafTupleData::tupstate, UnlockReleaseBuffer(), and SpGistScanOpaqueData::want_itup.
Referenced by spggetbitmap(), and spggettuple().
{ Buffer buffer = InvalidBuffer; bool reportedSome = false; while (scanWholeIndex || !reportedSome) { ScanStackEntry *stackEntry; BlockNumber blkno; OffsetNumber offset; Page page; bool isnull; /* Pull next to-do item from the list */ if (so->scanStack == NIL) break; /* there are no more pages to scan */ stackEntry = (ScanStackEntry *) linitial(so->scanStack); so->scanStack = list_delete_first(so->scanStack); redirect: /* Check for interrupts, just in case of infinite loop */ CHECK_FOR_INTERRUPTS(); blkno = ItemPointerGetBlockNumber(&stackEntry->ptr); offset = ItemPointerGetOffsetNumber(&stackEntry->ptr); if (buffer == InvalidBuffer) { buffer = ReadBuffer(index, blkno); LockBuffer(buffer, BUFFER_LOCK_SHARE); } else if (blkno != BufferGetBlockNumber(buffer)) { UnlockReleaseBuffer(buffer); buffer = ReadBuffer(index, blkno); LockBuffer(buffer, BUFFER_LOCK_SHARE); } /* else new pointer points to the same page, no work needed */ page = BufferGetPage(buffer); isnull = SpGistPageStoresNulls(page) ? true : false; if (SpGistPageIsLeaf(page)) { SpGistLeafTuple leafTuple; OffsetNumber max = PageGetMaxOffsetNumber(page); Datum leafValue = (Datum) 0; bool recheck = false; if (SpGistBlockIsRoot(blkno)) { /* When root is a leaf, examine all its tuples */ for (offset = FirstOffsetNumber; offset <= max; offset++) { leafTuple = (SpGistLeafTuple) PageGetItem(page, PageGetItemId(page, offset)); if (leafTuple->tupstate != SPGIST_LIVE) { /* all tuples on root should be live */ elog(ERROR, "unexpected SPGiST tuple state: %d", leafTuple->tupstate); } Assert(ItemPointerIsValid(&leafTuple->heapPtr)); if (spgLeafTest(index, so, leafTuple, isnull, stackEntry->level, stackEntry->reconstructedValue, &leafValue, &recheck)) { storeRes(so, &leafTuple->heapPtr, leafValue, isnull, recheck); reportedSome = true; } } } else { /* Normal case: just examine the chain we arrived at */ while (offset != InvalidOffsetNumber) { Assert(offset >= FirstOffsetNumber && offset <= max); leafTuple = (SpGistLeafTuple) PageGetItem(page, PageGetItemId(page, offset)); if (leafTuple->tupstate != SPGIST_LIVE) { if (leafTuple->tupstate == SPGIST_REDIRECT) { /* redirection tuple should be first in chain */ Assert(offset == ItemPointerGetOffsetNumber(&stackEntry->ptr)); /* transfer attention to redirect point */ stackEntry->ptr = ((SpGistDeadTuple) leafTuple)->pointer; Assert(ItemPointerGetBlockNumber(&stackEntry->ptr) != SPGIST_METAPAGE_BLKNO); goto redirect; } if (leafTuple->tupstate == SPGIST_DEAD) { /* dead tuple should be first in chain */ Assert(offset == ItemPointerGetOffsetNumber(&stackEntry->ptr)); /* No live entries on this page */ Assert(leafTuple->nextOffset == InvalidOffsetNumber); break; } /* We should not arrive at a placeholder */ elog(ERROR, "unexpected SPGiST tuple state: %d", leafTuple->tupstate); } Assert(ItemPointerIsValid(&leafTuple->heapPtr)); if (spgLeafTest(index, so, leafTuple, isnull, stackEntry->level, stackEntry->reconstructedValue, &leafValue, &recheck)) { storeRes(so, &leafTuple->heapPtr, leafValue, isnull, recheck); reportedSome = true; } offset = leafTuple->nextOffset; } } } else /* page is inner */ { SpGistInnerTuple innerTuple; spgInnerConsistentIn in; spgInnerConsistentOut out; FmgrInfo *procinfo; SpGistNodeTuple *nodes; SpGistNodeTuple node; int i; MemoryContext oldCtx; innerTuple = (SpGistInnerTuple) PageGetItem(page, PageGetItemId(page, offset)); if (innerTuple->tupstate != SPGIST_LIVE) { if (innerTuple->tupstate == SPGIST_REDIRECT) { /* transfer attention to redirect point */ stackEntry->ptr = ((SpGistDeadTuple) innerTuple)->pointer; Assert(ItemPointerGetBlockNumber(&stackEntry->ptr) != SPGIST_METAPAGE_BLKNO); goto redirect; } elog(ERROR, "unexpected SPGiST tuple state: %d", innerTuple->tupstate); } /* use temp context for calling inner_consistent */ oldCtx = MemoryContextSwitchTo(so->tempCxt); in.scankeys = so->keyData; in.nkeys = so->numberOfKeys; in.reconstructedValue = stackEntry->reconstructedValue; in.level = stackEntry->level; in.returnData = so->want_itup; in.allTheSame = innerTuple->allTheSame; in.hasPrefix = (innerTuple->prefixSize > 0); in.prefixDatum = SGITDATUM(innerTuple, &so->state); in.nNodes = innerTuple->nNodes; in.nodeLabels = spgExtractNodeLabels(&so->state, innerTuple); /* collect node pointers */ nodes = (SpGistNodeTuple *) palloc(sizeof(SpGistNodeTuple) * in.nNodes); SGITITERATE(innerTuple, i, node) { nodes[i] = node; } memset(&out, 0, sizeof(out)); if (!isnull) { /* use user-defined inner consistent method */ procinfo = index_getprocinfo(index, 1, SPGIST_INNER_CONSISTENT_PROC); FunctionCall2Coll(procinfo, index->rd_indcollation[0], PointerGetDatum(&in), PointerGetDatum(&out)); } else { /* force all children to be visited */ out.nNodes = in.nNodes; out.nodeNumbers = (int *) palloc(sizeof(int) * in.nNodes); for (i = 0; i < in.nNodes; i++) out.nodeNumbers[i] = i; } MemoryContextSwitchTo(oldCtx); /* If allTheSame, they should all or none of 'em match */ if (innerTuple->allTheSame) if (out.nNodes != 0 && out.nNodes != in.nNodes) elog(ERROR, "inconsistent inner_consistent results for allTheSame inner tuple"); for (i = 0; i < out.nNodes; i++) { int nodeN = out.nodeNumbers[i]; Assert(nodeN >= 0 && nodeN < in.nNodes); if (ItemPointerIsValid(&nodes[nodeN]->t_tid)) { ScanStackEntry *newEntry; /* Create new work item for this node */ newEntry = palloc(sizeof(ScanStackEntry)); newEntry->ptr = nodes[nodeN]->t_tid; if (out.levelAdds) newEntry->level = stackEntry->level + out.levelAdds[i]; else newEntry->level = stackEntry->level; /* Must copy value out of temp context */ if (out.reconstructedValues) newEntry->reconstructedValue = datumCopy(out.reconstructedValues[i], so->state.attType.attbyval, so->state.attType.attlen); else newEntry->reconstructedValue = (Datum) 0; so->scanStack = lcons(newEntry, so->scanStack); } } } /* done with this scan stack entry */ freeScanStackEntry(so, stackEntry); /* clear temp context before proceeding to the next one */ MemoryContextReset(so->tempCxt); } if (buffer != InvalidBuffer) UnlockReleaseBuffer(buffer); }
static void storeBitmap | ( | SpGistScanOpaque | so, | |
ItemPointer | heapPtr, | |||
Datum | leafValue, | |||
bool | isnull, | |||
bool | recheck | |||
) | [static] |
Definition at line 567 of file spgscan.c.
References SpGistScanOpaqueData::ntids, SpGistScanOpaqueData::tbm, and tbm_add_tuples().
Referenced by spggetbitmap().
{ tbm_add_tuples(so->tbm, heapPtr, 1, recheck); so->ntids++; }
static void storeGettuple | ( | SpGistScanOpaque | so, | |
ItemPointer | heapPtr, | |||
Datum | leafValue, | |||
bool | isnull, | |||
bool | recheck | |||
) | [static] |
Definition at line 594 of file spgscan.c.
References Assert, SpGistScanOpaqueData::heapPtrs, index_form_tuple(), SpGistScanOpaqueData::indexTupDesc, SpGistScanOpaqueData::indexTups, MaxIndexTuplesPerPage, SpGistScanOpaqueData::nPtrs, SpGistScanOpaqueData::recheck, and SpGistScanOpaqueData::want_itup.
Referenced by spggettuple().
{ Assert(so->nPtrs < MaxIndexTuplesPerPage); so->heapPtrs[so->nPtrs] = *heapPtr; so->recheck[so->nPtrs] = recheck; if (so->want_itup) { /* * Reconstruct desired IndexTuple. We have to copy the datum out of * the temp context anyway, so we may as well create the tuple here. */ so->indexTups[so->nPtrs] = index_form_tuple(so->indexTupDesc, &leafValue, &isnull); } so->nPtrs++; }