#include "access/skey.h"
#include "access/xlog.h"
#include "fmgr.h"
Go to the source code of this file.
#define SPGIST_CHOOSE_PROC 2 |
Definition at line 28 of file spgist.h.
Referenced by spgdoinsert().
#define SPGIST_CONFIG_PROC 1 |
Definition at line 27 of file spgist.h.
Referenced by spgGetCache().
#define SPGIST_DEFAULT_FILLFACTOR 80 |
Definition at line 24 of file spgist.h.
Referenced by SpGistGetBuffer().
#define SPGIST_INNER_CONSISTENT_PROC 4 |
#define SPGIST_LEAF_CONSISTENT_PROC 5 |
Definition at line 31 of file spgist.h.
Referenced by spgLeafTest().
#define SPGIST_PICKSPLIT_PROC 3 |
Definition at line 29 of file spgist.h.
Referenced by doPickSplit().
typedef struct spgChooseIn spgChooseIn |
typedef struct spgChooseOut spgChooseOut |
typedef enum spgChooseResultType spgChooseResultType |
typedef struct spgConfigIn spgConfigIn |
typedef struct spgConfigOut spgConfigOut |
typedef struct spgInnerConsistentIn spgInnerConsistentIn |
typedef struct spgInnerConsistentOut spgInnerConsistentOut |
typedef struct spgLeafConsistentIn spgLeafConsistentIn |
typedef struct spgLeafConsistentOut spgLeafConsistentOut |
typedef struct spgPickSplitIn spgPickSplitIn |
typedef struct spgPickSplitOut spgPickSplitOut |
enum spgChooseResultType |
Definition at line 67 of file spgist.h.
{ spgMatchNode = 1, /* descend into existing node */ spgAddNode, /* add a node to the inner tuple */ spgSplitTuple /* split inner tuple (change its prefix) */ } spgChooseResultType;
void spg_desc | ( | StringInfo | buf, | |
uint8 | xl_info, | |||
char * | rec | |||
) |
Definition at line 27 of file spgdesc.c.
References appendStringInfo(), out_target(), XLOG_SPGIST_ADD_LEAF, XLOG_SPGIST_ADD_NODE, XLOG_SPGIST_CREATE_INDEX, XLOG_SPGIST_MOVE_LEAFS, XLOG_SPGIST_PICKSPLIT, XLOG_SPGIST_SPLIT_TUPLE, XLOG_SPGIST_VACUUM_LEAF, XLOG_SPGIST_VACUUM_REDIRECT, and XLOG_SPGIST_VACUUM_ROOT.
{ uint8 info = xl_info & ~XLR_INFO_MASK; switch (info) { case XLOG_SPGIST_CREATE_INDEX: appendStringInfo(buf, "create_index: rel %u/%u/%u", ((RelFileNode *) rec)->spcNode, ((RelFileNode *) rec)->dbNode, ((RelFileNode *) rec)->relNode); break; case XLOG_SPGIST_ADD_LEAF: out_target(buf, ((spgxlogAddLeaf *) rec)->node); appendStringInfo(buf, "add leaf to page: %u", ((spgxlogAddLeaf *) rec)->blknoLeaf); break; case XLOG_SPGIST_MOVE_LEAFS: out_target(buf, ((spgxlogMoveLeafs *) rec)->node); appendStringInfo(buf, "move %u leafs from page %u to page %u", ((spgxlogMoveLeafs *) rec)->nMoves, ((spgxlogMoveLeafs *) rec)->blknoSrc, ((spgxlogMoveLeafs *) rec)->blknoDst); break; case XLOG_SPGIST_ADD_NODE: out_target(buf, ((spgxlogAddNode *) rec)->node); appendStringInfo(buf, "add node to %u:%u", ((spgxlogAddNode *) rec)->blkno, ((spgxlogAddNode *) rec)->offnum); break; case XLOG_SPGIST_SPLIT_TUPLE: out_target(buf, ((spgxlogSplitTuple *) rec)->node); appendStringInfo(buf, "split node %u:%u to %u:%u", ((spgxlogSplitTuple *) rec)->blknoPrefix, ((spgxlogSplitTuple *) rec)->offnumPrefix, ((spgxlogSplitTuple *) rec)->blknoPostfix, ((spgxlogSplitTuple *) rec)->offnumPostfix); break; case XLOG_SPGIST_PICKSPLIT: out_target(buf, ((spgxlogPickSplit *) rec)->node); appendStringInfo(buf, "split leaf page"); break; case XLOG_SPGIST_VACUUM_LEAF: out_target(buf, ((spgxlogVacuumLeaf *) rec)->node); appendStringInfo(buf, "vacuum leaf tuples on page %u", ((spgxlogVacuumLeaf *) rec)->blkno); break; case XLOG_SPGIST_VACUUM_ROOT: out_target(buf, ((spgxlogVacuumRoot *) rec)->node); appendStringInfo(buf, "vacuum leaf tuples on root page %u", ((spgxlogVacuumRoot *) rec)->blkno); break; case XLOG_SPGIST_VACUUM_REDIRECT: out_target(buf, ((spgxlogVacuumRedirect *) rec)->node); appendStringInfo(buf, "vacuum redirect tuples on page %u, newest XID %u", ((spgxlogVacuumRedirect *) rec)->blkno, ((spgxlogVacuumRedirect *) rec)->newestRedirectXid); break; default: appendStringInfo(buf, "unknown spgist op code %u", info); break; } }
void spg_redo | ( | XLogRecPtr | lsn, | |
XLogRecord * | record | |||
) |
Definition at line 1052 of file spgxlog.c.
References elog, MemoryContextReset(), MemoryContextSwitchTo(), PANIC, spgRedoAddLeaf(), spgRedoAddNode(), spgRedoCreateIndex(), spgRedoMoveLeafs(), spgRedoPickSplit(), spgRedoSplitTuple(), spgRedoVacuumLeaf(), spgRedoVacuumRedirect(), spgRedoVacuumRoot(), XLogRecord::xl_info, XLOG_SPGIST_ADD_LEAF, XLOG_SPGIST_ADD_NODE, XLOG_SPGIST_CREATE_INDEX, XLOG_SPGIST_MOVE_LEAFS, XLOG_SPGIST_PICKSPLIT, XLOG_SPGIST_SPLIT_TUPLE, XLOG_SPGIST_VACUUM_LEAF, XLOG_SPGIST_VACUUM_REDIRECT, and XLOG_SPGIST_VACUUM_ROOT.
{ uint8 info = record->xl_info & ~XLR_INFO_MASK; MemoryContext oldCxt; oldCxt = MemoryContextSwitchTo(opCtx); switch (info) { case XLOG_SPGIST_CREATE_INDEX: spgRedoCreateIndex(lsn, record); break; case XLOG_SPGIST_ADD_LEAF: spgRedoAddLeaf(lsn, record); break; case XLOG_SPGIST_MOVE_LEAFS: spgRedoMoveLeafs(lsn, record); break; case XLOG_SPGIST_ADD_NODE: spgRedoAddNode(lsn, record); break; case XLOG_SPGIST_SPLIT_TUPLE: spgRedoSplitTuple(lsn, record); break; case XLOG_SPGIST_PICKSPLIT: spgRedoPickSplit(lsn, record); break; case XLOG_SPGIST_VACUUM_LEAF: spgRedoVacuumLeaf(lsn, record); break; case XLOG_SPGIST_VACUUM_ROOT: spgRedoVacuumRoot(lsn, record); break; case XLOG_SPGIST_VACUUM_REDIRECT: spgRedoVacuumRedirect(lsn, record); break; default: elog(PANIC, "spg_redo: unknown op code %u", info); } MemoryContextSwitchTo(oldCxt); MemoryContextReset(opCtx); }
void spg_xlog_cleanup | ( | void | ) |
Definition at line 1106 of file spgxlog.c.
References MemoryContextDelete().
{ MemoryContextDelete(opCtx); opCtx = NULL; }
void spg_xlog_startup | ( | void | ) |
Definition at line 1096 of file spgxlog.c.
References ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, ALLOCSET_DEFAULT_MINSIZE, AllocSetContextCreate(), and CurrentMemoryContext.
{ opCtx = AllocSetContextCreate(CurrentMemoryContext, "SP-GiST temporary context", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); }
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 spgbuild | ( | PG_FUNCTION_ARGS | ) |
Definition at line 58 of file spginsert.c.
References ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, ALLOCSET_DEFAULT_MINSIZE, AllocSetContextCreate(), Assert, XLogRecData::buffer, BufferGetBlockNumber(), BufferGetPage, CurrentMemoryContext, XLogRecData::data, elog, END_CRIT_SECTION, ERROR, IndexBuildResult::heap_tuples, IndexBuildResult::index_tuples, IndexBuildHeapScan(), initSpGistState(), SpGistState::isBuild, XLogRecData::len, MarkBufferDirty(), MemoryContextDelete(), XLogRecData::next, PageSetLSN, palloc0(), PG_GETARG_POINTER, PG_RETURN_POINTER, RelationData::rd_node, RelationGetNumberOfBlocks, RelationGetRelationName, RelationNeedsWAL, SPGIST_LEAF, SPGIST_METAPAGE_BLKNO, SPGIST_NULL_BLKNO, SPGIST_NULLS, SPGIST_ROOT_BLKNO, spgistBuildCallback(), SpGistInitBuffer(), SpGistInitMetapage(), SpGistNewBuffer(), SpGistUpdateMetaPage(), SpGistBuildState::spgstate, START_CRIT_SECTION, SpGistBuildState::tmpCtx, UnlockReleaseBuffer(), XLOG_SPGIST_CREATE_INDEX, and XLogInsert().
{ Relation heap = (Relation) PG_GETARG_POINTER(0); Relation index = (Relation) PG_GETARG_POINTER(1); IndexInfo *indexInfo = (IndexInfo *) PG_GETARG_POINTER(2); IndexBuildResult *result; double reltuples; SpGistBuildState buildstate; Buffer metabuffer, rootbuffer, nullbuffer; if (RelationGetNumberOfBlocks(index) != 0) elog(ERROR, "index \"%s\" already contains data", RelationGetRelationName(index)); /* * Initialize the meta page and root pages */ metabuffer = SpGistNewBuffer(index); rootbuffer = SpGistNewBuffer(index); nullbuffer = SpGistNewBuffer(index); Assert(BufferGetBlockNumber(metabuffer) == SPGIST_METAPAGE_BLKNO); Assert(BufferGetBlockNumber(rootbuffer) == SPGIST_ROOT_BLKNO); Assert(BufferGetBlockNumber(nullbuffer) == SPGIST_NULL_BLKNO); START_CRIT_SECTION(); SpGistInitMetapage(BufferGetPage(metabuffer)); MarkBufferDirty(metabuffer); SpGistInitBuffer(rootbuffer, SPGIST_LEAF); MarkBufferDirty(rootbuffer); SpGistInitBuffer(nullbuffer, SPGIST_LEAF | SPGIST_NULLS); MarkBufferDirty(nullbuffer); if (RelationNeedsWAL(index)) { XLogRecPtr recptr; XLogRecData rdata; /* WAL data is just the relfilenode */ rdata.data = (char *) &(index->rd_node); rdata.len = sizeof(RelFileNode); rdata.buffer = InvalidBuffer; rdata.next = NULL; recptr = XLogInsert(RM_SPGIST_ID, XLOG_SPGIST_CREATE_INDEX, &rdata); PageSetLSN(BufferGetPage(metabuffer), recptr); PageSetLSN(BufferGetPage(rootbuffer), recptr); PageSetLSN(BufferGetPage(nullbuffer), recptr); } END_CRIT_SECTION(); UnlockReleaseBuffer(metabuffer); UnlockReleaseBuffer(rootbuffer); UnlockReleaseBuffer(nullbuffer); /* * Now insert all the heap data into the index */ initSpGistState(&buildstate.spgstate, index); buildstate.spgstate.isBuild = true; buildstate.tmpCtx = AllocSetContextCreate(CurrentMemoryContext, "SP-GiST build temporary context", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); reltuples = IndexBuildHeapScan(heap, index, indexInfo, true, spgistBuildCallback, (void *) &buildstate); MemoryContextDelete(buildstate.tmpCtx); SpGistUpdateMetaPage(index); result = (IndexBuildResult *) palloc0(sizeof(IndexBuildResult)); result->heap_tuples = result->index_tuples = reltuples; PG_RETURN_POINTER(result); }
Datum spgbuildempty | ( | PG_FUNCTION_ARGS | ) |
Definition at line 147 of file spginsert.c.
References INIT_FORKNUM, log_newpage(), RelFileNodeBackend::node, PageSetChecksumInplace(), palloc(), PG_GETARG_POINTER, PG_RETURN_VOID, RelationData::rd_smgr, SMgrRelationData::smgr_rnode, smgrimmedsync(), smgrwrite(), SPGIST_LEAF, SPGIST_METAPAGE_BLKNO, SPGIST_NULL_BLKNO, SPGIST_NULLS, SPGIST_ROOT_BLKNO, SpGistInitMetapage(), SpGistInitPage(), and XLogIsNeeded.
{ Relation index = (Relation) PG_GETARG_POINTER(0); Page page; /* Construct metapage. */ page = (Page) palloc(BLCKSZ); SpGistInitMetapage(page); /* Write the page. If archiving/streaming, XLOG it. */ PageSetChecksumInplace(page, SPGIST_METAPAGE_BLKNO); smgrwrite(index->rd_smgr, INIT_FORKNUM, SPGIST_METAPAGE_BLKNO, (char *) page, true); if (XLogIsNeeded()) log_newpage(&index->rd_smgr->smgr_rnode.node, INIT_FORKNUM, SPGIST_METAPAGE_BLKNO, page); /* Likewise for the root page. */ SpGistInitPage(page, SPGIST_LEAF); PageSetChecksumInplace(page, SPGIST_ROOT_BLKNO); smgrwrite(index->rd_smgr, INIT_FORKNUM, SPGIST_ROOT_BLKNO, (char *) page, true); if (XLogIsNeeded()) log_newpage(&index->rd_smgr->smgr_rnode.node, INIT_FORKNUM, SPGIST_ROOT_BLKNO, page); /* Likewise for the null-tuples root page. */ SpGistInitPage(page, SPGIST_LEAF | SPGIST_NULLS); PageSetChecksumInplace(page, SPGIST_NULL_BLKNO); smgrwrite(index->rd_smgr, INIT_FORKNUM, SPGIST_NULL_BLKNO, (char *) page, true); if (XLogIsNeeded()) log_newpage(&index->rd_smgr->smgr_rnode.node, INIT_FORKNUM, SPGIST_NULL_BLKNO, page); /* * An immediate sync is required even if we xlog'd the pages, because the * writes did not go through shared buffers and therefore a concurrent * checkpoint may have moved the redo pointer past our xlog record. */ smgrimmedsync(index->rd_smgr, INIT_FORKNUM); PG_RETURN_VOID(); }
Datum spgbulkdelete | ( | PG_FUNCTION_ARGS | ) |
Definition at line 894 of file spgvacuum.c.
References spgBulkDeleteState::callback, callback(), spgBulkDeleteState::callback_state, spgBulkDeleteState::info, NULL, palloc0(), PG_GETARG_POINTER, PG_RETURN_POINTER, spgvacuumscan(), and spgBulkDeleteState::stats.
{ IndexVacuumInfo *info = (IndexVacuumInfo *) PG_GETARG_POINTER(0); IndexBulkDeleteResult *stats = (IndexBulkDeleteResult *) PG_GETARG_POINTER(1); IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(2); void *callback_state = (void *) PG_GETARG_POINTER(3); spgBulkDeleteState bds; /* allocate stats if first time through, else re-use existing struct */ if (stats == NULL) stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult)); bds.info = info; bds.stats = stats; bds.callback = callback; bds.callback_state = callback_state; spgvacuumscan(&bds); PG_RETURN_POINTER(stats); }
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); }
Datum spginsert | ( | PG_FUNCTION_ARGS | ) |
Definition at line 198 of file spginsert.c.
References ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, ALLOCSET_DEFAULT_MINSIZE, AllocSetContextCreate(), CurrentMemoryContext, initSpGistState(), MemoryContextDelete(), MemoryContextSwitchTo(), PG_GETARG_INT32, PG_GETARG_POINTER, PG_RETURN_BOOL, spgdoinsert(), SpGistUpdateMetaPage(), and values.
{ Relation index = (Relation) PG_GETARG_POINTER(0); Datum *values = (Datum *) PG_GETARG_POINTER(1); bool *isnull = (bool *) PG_GETARG_POINTER(2); ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3); #ifdef NOT_USED Relation heapRel = (Relation) PG_GETARG_POINTER(4); IndexUniqueCheck checkUnique = (IndexUniqueCheck) PG_GETARG_INT32(5); #endif SpGistState spgstate; MemoryContext oldCtx; MemoryContext insertCtx; insertCtx = AllocSetContextCreate(CurrentMemoryContext, "SP-GiST insert temporary context", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); oldCtx = MemoryContextSwitchTo(insertCtx); initSpGistState(&spgstate, index); spgdoinsert(index, &spgstate, ht_ctid, *values, *isnull); SpGistUpdateMetaPage(index); MemoryContextSwitchTo(oldCtx); MemoryContextDelete(insertCtx); /* return false since we've not done any unique check */ PG_RETURN_BOOL(false); }
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(); }
Datum spgoptions | ( | PG_FUNCTION_ARGS | ) |
Definition at line 493 of file spgutils.c.
References default_reloptions(), PG_GETARG_BOOL, PG_GETARG_DATUM, PG_RETURN_BYTEA_P, PG_RETURN_NULL, and RELOPT_KIND_SPGIST.
{ Datum reloptions = PG_GETARG_DATUM(0); bool validate = PG_GETARG_BOOL(1); bytea *result; result = default_reloptions(reloptions, validate, RELOPT_KIND_SPGIST); if (result) PG_RETURN_BYTEA_P(result); PG_RETURN_NULL(); }
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(); }
Datum spgvacuumcleanup | ( | PG_FUNCTION_ARGS | ) |
Definition at line 928 of file spgvacuum.c.
References IndexVacuumInfo::analyze_only, spgBulkDeleteState::callback, spgBulkDeleteState::callback_state, IndexVacuumInfo::estimated_count, IndexVacuumInfo::index, IndexFreeSpaceMapVacuum(), spgBulkDeleteState::info, NULL, IndexVacuumInfo::num_heap_tuples, IndexBulkDeleteResult::num_index_tuples, palloc0(), PG_GETARG_POINTER, PG_RETURN_POINTER, spgvacuumscan(), and spgBulkDeleteState::stats.
{ IndexVacuumInfo *info = (IndexVacuumInfo *) PG_GETARG_POINTER(0); IndexBulkDeleteResult *stats = (IndexBulkDeleteResult *) PG_GETARG_POINTER(1); Relation index = info->index; spgBulkDeleteState bds; /* No-op in ANALYZE ONLY mode */ if (info->analyze_only) PG_RETURN_POINTER(stats); /* * We don't need to scan the index if there was a preceding bulkdelete * pass. Otherwise, make a pass that won't delete any live tuples, but * might still accomplish useful stuff with redirect/placeholder cleanup, * and in any case will provide stats. */ if (stats == NULL) { stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult)); bds.info = info; bds.stats = stats; bds.callback = dummy_callback; bds.callback_state = NULL; spgvacuumscan(&bds); } /* Finally, vacuum the FSM */ IndexFreeSpaceMapVacuum(index); /* * It's quite possible for us to be fooled by concurrent tuple moves into * double-counting some index tuples, so disbelieve any total that exceeds * the underlying heap's count ... if we know that accurately. Otherwise * this might just make matters worse. */ if (!info->estimated_count) { if (stats->num_index_tuples > info->num_heap_tuples) stats->num_index_tuples = info->num_heap_tuples; } PG_RETURN_POINTER(stats); }