PostgreSQL Source Code  git master
spgist.h File Reference
#include "access/amapi.h"
#include "access/xlogreader.h"
#include "fmgr.h"
#include "lib/stringinfo.h"
Include dependency graph for spgist.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  spgConfigIn
 
struct  spgConfigOut
 
struct  spgChooseIn
 
struct  spgChooseOut
 
struct  spgPickSplitIn
 
struct  spgPickSplitOut
 
struct  spgInnerConsistentIn
 
struct  spgInnerConsistentOut
 
struct  spgLeafConsistentIn
 
struct  spgLeafConsistentOut
 

Macros

#define SPGIST_MIN_FILLFACTOR   10
 
#define SPGIST_DEFAULT_FILLFACTOR   80
 
#define SPGIST_CONFIG_PROC   1
 
#define SPGIST_CHOOSE_PROC   2
 
#define SPGIST_PICKSPLIT_PROC   3
 
#define SPGIST_INNER_CONSISTENT_PROC   4
 
#define SPGIST_LEAF_CONSISTENT_PROC   5
 
#define SPGIST_COMPRESS_PROC   6
 
#define SPGISTNRequiredProc   5
 
#define SPGISTNProc   6
 

Typedefs

typedef struct spgConfigIn spgConfigIn
 
typedef struct spgConfigOut spgConfigOut
 
typedef struct spgChooseIn spgChooseIn
 
typedef enum spgChooseResultType spgChooseResultType
 
typedef struct spgChooseOut spgChooseOut
 
typedef struct spgPickSplitIn spgPickSplitIn
 
typedef struct spgPickSplitOut spgPickSplitOut
 
typedef struct spgInnerConsistentIn spgInnerConsistentIn
 
typedef struct spgInnerConsistentOut spgInnerConsistentOut
 
typedef struct spgLeafConsistentIn spgLeafConsistentIn
 
typedef struct spgLeafConsistentOut spgLeafConsistentOut
 

Enumerations

enum  spgChooseResultType { spgMatchNode = 1, spgAddNode, spgSplitTuple }
 

Functions

byteaspgoptions (Datum reloptions, bool validate)
 
IndexBuildResultspgbuild (Relation heap, Relation index, struct IndexInfo *indexInfo)
 
void spgbuildempty (Relation index)
 
bool spginsert (Relation index, Datum *values, bool *isnull, ItemPointer ht_ctid, Relation heapRel, IndexUniqueCheck checkUnique, struct IndexInfo *indexInfo)
 
IndexScanDesc spgbeginscan (Relation rel, int keysz, int orderbysz)
 
void spgendscan (IndexScanDesc scan)
 
void spgrescan (IndexScanDesc scan, ScanKey scankey, int nscankeys, ScanKey orderbys, int norderbys)
 
int64 spggetbitmap (IndexScanDesc scan, TIDBitmap *tbm)
 
bool spggettuple (IndexScanDesc scan, ScanDirection dir)
 
bool spgcanreturn (Relation index, int attno)
 
IndexBulkDeleteResultspgbulkdelete (IndexVacuumInfo *info, IndexBulkDeleteResult *stats, IndexBulkDeleteCallback callback, void *callback_state)
 
IndexBulkDeleteResultspgvacuumcleanup (IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
 
bool spgvalidate (Oid opclassoid)
 

Macro Definition Documentation

◆ SPGIST_CHOOSE_PROC

#define SPGIST_CHOOSE_PROC   2

Definition at line 29 of file spgist.h.

Referenced by spgdoinsert(), and spgvalidate().

◆ SPGIST_COMPRESS_PROC

#define SPGIST_COMPRESS_PROC   6

Definition at line 33 of file spgist.h.

Referenced by spgdoinsert(), spgGetCache(), and spgvalidate().

◆ SPGIST_CONFIG_PROC

#define SPGIST_CONFIG_PROC   1

Definition at line 28 of file spgist.h.

Referenced by spgGetCache(), and spgvalidate().

◆ SPGIST_DEFAULT_FILLFACTOR

#define SPGIST_DEFAULT_FILLFACTOR   80

Definition at line 25 of file spgist.h.

Referenced by SpGistGetBuffer().

◆ SPGIST_INNER_CONSISTENT_PROC

#define SPGIST_INNER_CONSISTENT_PROC   4

Definition at line 31 of file spgist.h.

Referenced by spgvalidate(), and spgWalk().

◆ SPGIST_LEAF_CONSISTENT_PROC

#define SPGIST_LEAF_CONSISTENT_PROC   5

Definition at line 32 of file spgist.h.

Referenced by spgLeafTest(), and spgvalidate().

◆ SPGIST_MIN_FILLFACTOR

#define SPGIST_MIN_FILLFACTOR   10

Definition at line 24 of file spgist.h.

◆ SPGIST_PICKSPLIT_PROC

#define SPGIST_PICKSPLIT_PROC   3

Definition at line 30 of file spgist.h.

Referenced by doPickSplit(), and spgvalidate().

◆ SPGISTNProc

#define SPGISTNProc   6

Definition at line 35 of file spgist.h.

Referenced by spghandler(), and spgvalidate().

◆ SPGISTNRequiredProc

#define SPGISTNRequiredProc   5

Definition at line 34 of file spgist.h.

Typedef Documentation

◆ spgChooseIn

◆ spgChooseOut

◆ spgChooseResultType

◆ spgConfigIn

◆ spgConfigOut

◆ spgInnerConsistentIn

◆ spgInnerConsistentOut

◆ spgLeafConsistentIn

◆ spgLeafConsistentOut

◆ spgPickSplitIn

◆ spgPickSplitOut

Enumeration Type Documentation

◆ spgChooseResultType

Enumerator
spgMatchNode 
spgAddNode 
spgSplitTuple 

Definition at line 71 of file spgist.h.

72 {
73  spgMatchNode = 1, /* descend into existing node */
74  spgAddNode, /* add a node to the inner tuple */
75  spgSplitTuple /* split inner tuple (change its prefix) */
spgChooseResultType
Definition: spgist.h:71

Function Documentation

◆ spgbeginscan()

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

Definition at line 181 of file spgscan.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, CurrentMemoryContext, IndexScanDescData::indexRelation, SpGistScanOpaqueData::indexTupDesc, initSpGistState(), SpGistScanOpaqueData::keyData, IndexScanDescData::opaque, palloc(), palloc0(), RelationGetDescr, RelationGetIndexScan(), SpGistScanOpaqueData::state, SpGistScanOpaqueData::tempCxt, SpGistScanOpaqueData::traversalCxt, and IndexScanDescData::xs_hitupdesc.

Referenced by spghandler().

182 {
183  IndexScanDesc scan;
184  SpGistScanOpaque so;
185 
186  scan = RelationGetIndexScan(rel, keysz, 0);
187 
189  if (keysz > 0)
190  so->keyData = (ScanKey) palloc(sizeof(ScanKeyData) * keysz);
191  else
192  so->keyData = NULL;
193  initSpGistState(&so->state, scan->indexRelation);
195  "SP-GiST search temporary context",
198  "SP-GiST traversal-value context",
200 
201  /* Set up indexTupDesc and xs_hitupdesc in case it's an index-only scan */
202  so->indexTupDesc = scan->xs_hitupdesc = RelationGetDescr(rel);
203 
204  scan->opaque = so;
205 
206  return scan;
207 }
#define RelationGetDescr(relation)
Definition: rel.h:433
MemoryContext tempCxt
TupleDesc xs_hitupdesc
Definition: relscan.h:118
Relation indexRelation
Definition: relscan.h:91
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
ScanKeyData * ScanKey
Definition: skey.h:75
void initSpGistState(SpGistState *state, Relation index)
Definition: spgutils.c:175
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:170
void * palloc0(Size size)
Definition: mcxt.c:955
SpGistScanOpaqueData * SpGistScanOpaque
MemoryContext traversalCxt
void * palloc(Size size)
Definition: mcxt.c:924
IndexScanDesc RelationGetIndexScan(Relation indexRelation, int nkeys, int norderbys)
Definition: genam.c:78

◆ spgbuild()

IndexBuildResult* spgbuild ( Relation  heap,
Relation  index,
struct IndexInfo indexInfo 
)

Definition at line 74 of file spginsert.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, BufferGetBlockNumber(), BufferGetPage, CurrentMemoryContext, elog, END_CRIT_SECTION, ERROR, IndexBuildResult::heap_tuples, IndexBuildResult::index_tuples, IndexBuildHeapScan(), SpGistBuildState::indtuples, initSpGistState(), SpGistState::isBuild, MarkBufferDirty(), MemoryContextDelete(), PageSetLSN, palloc0(), REGBUF_STANDARD, REGBUF_WILL_INIT, RelationGetNumberOfBlocks, RelationGetRelationName, RelationNeedsWAL, reltuples, 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, XLogBeginInsert(), XLogInsert(), and XLogRegisterBuffer().

Referenced by spghandler().

75 {
76  IndexBuildResult *result;
77  double reltuples;
78  SpGistBuildState buildstate;
79  Buffer metabuffer,
80  rootbuffer,
81  nullbuffer;
82 
83  if (RelationGetNumberOfBlocks(index) != 0)
84  elog(ERROR, "index \"%s\" already contains data",
86 
87  /*
88  * Initialize the meta page and root pages
89  */
90  metabuffer = SpGistNewBuffer(index);
91  rootbuffer = SpGistNewBuffer(index);
92  nullbuffer = SpGistNewBuffer(index);
93 
97 
99 
100  SpGistInitMetapage(BufferGetPage(metabuffer));
101  MarkBufferDirty(metabuffer);
102  SpGistInitBuffer(rootbuffer, SPGIST_LEAF);
103  MarkBufferDirty(rootbuffer);
105  MarkBufferDirty(nullbuffer);
106 
107  if (RelationNeedsWAL(index))
108  {
109  XLogRecPtr recptr;
110 
111  XLogBeginInsert();
112 
113  /*
114  * Replay will re-initialize the pages, so don't take full pages
115  * images. No other data to log.
116  */
120 
121  recptr = XLogInsert(RM_SPGIST_ID, XLOG_SPGIST_CREATE_INDEX);
122 
123  PageSetLSN(BufferGetPage(metabuffer), recptr);
124  PageSetLSN(BufferGetPage(rootbuffer), recptr);
125  PageSetLSN(BufferGetPage(nullbuffer), recptr);
126  }
127 
129 
130  UnlockReleaseBuffer(metabuffer);
131  UnlockReleaseBuffer(rootbuffer);
132  UnlockReleaseBuffer(nullbuffer);
133 
134  /*
135  * Now insert all the heap data into the index
136  */
137  initSpGistState(&buildstate.spgstate, index);
138  buildstate.spgstate.isBuild = true;
139  buildstate.indtuples = 0;
140 
142  "SP-GiST build temporary context",
144 
145  reltuples = IndexBuildHeapScan(heap, index, indexInfo, true,
146  spgistBuildCallback, (void *) &buildstate,
147  NULL);
148 
149  MemoryContextDelete(buildstate.tmpCtx);
150 
151  SpGistUpdateMetaPage(index);
152 
153  result = (IndexBuildResult *) palloc0(sizeof(IndexBuildResult));
154  result->heap_tuples = reltuples;
155  result->index_tuples = buildstate.indtuples;
156 
157  return result;
158 }
void SpGistUpdateMetaPage(Relation index)
Definition: spgutils.c:270
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:213
#define END_CRIT_SECTION()
Definition: miscadmin.h:133
#define SPGIST_NULLS
#define REGBUF_WILL_INIT
Definition: xloginsert.h:32
#define START_CRIT_SECTION()
Definition: miscadmin.h:131
SpGistState spgstate
Definition: spginsert.c:34
#define SPGIST_ROOT_BLKNO
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
#define ERROR
Definition: elog.h:43
#define XLOG_SPGIST_CREATE_INDEX
Definition: spgxlog.h:21
double IndexBuildHeapScan(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, bool allow_sync, IndexBuildCallback callback, void *callback_state, HeapScanDesc scan)
Definition: index.c:2418
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
#define SPGIST_NULL_BLKNO
#define REGBUF_STANDARD
Definition: xloginsert.h:34
#define SPGIST_METAPAGE_BLKNO
void initSpGistState(SpGistState *state, Relation index)
Definition: spgutils.c:175
#define RelationGetRelationName(relation)
Definition: rel.h:441
static void spgistBuildCallback(Relation index, HeapTuple htup, Datum *values, bool *isnull, bool tupleIsAlive, void *state)
Definition: spginsert.c:42
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
void SpGistInitBuffer(Buffer b, uint16 f)
Definition: spgutils.c:544
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:170
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
void * palloc0(Size size)
Definition: mcxt.c:955
#define RelationGetNumberOfBlocks(reln)
Definition: bufmgr.h:199
Buffer SpGistNewBuffer(Relation index)
Definition: spgutils.c:205
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:699
void SpGistInitMetapage(Page page)
Definition: spgutils.c:554
#define RelationNeedsWAL(relation)
Definition: rel.h:510
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2605
MemoryContext tmpCtx
Definition: spginsert.c:36
#define elog
Definition: elog.h:219
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define SPGIST_LEAF
#define PageSetLSN(page, lsn)
Definition: bufpage.h:364
int Buffer
Definition: buf.h:23
float4 reltuples
Definition: pg_class.h:44
double index_tuples
Definition: genam.h:33
double heap_tuples
Definition: genam.h:32

◆ spgbuildempty()

void spgbuildempty ( Relation  index)

Definition at line 164 of file spginsert.c.

References INIT_FORKNUM, log_newpage(), RelFileNodeBackend::node, PageSetChecksumInplace(), palloc(), RelationData::rd_smgr, SMgrRelationData::smgr_rnode, smgrimmedsync(), smgrwrite(), SPGIST_LEAF, SPGIST_METAPAGE_BLKNO, SPGIST_NULL_BLKNO, SPGIST_NULLS, SPGIST_ROOT_BLKNO, SpGistInitMetapage(), and SpGistInitPage().

Referenced by spghandler().

165 {
166  Page page;
167 
168  /* Construct metapage. */
169  page = (Page) palloc(BLCKSZ);
170  SpGistInitMetapage(page);
171 
172  /*
173  * Write the page and log it unconditionally. This is important
174  * particularly for indexes created on tablespaces and databases whose
175  * creation happened after the last redo pointer as recovery removes any
176  * of their existing content when the corresponding create records are
177  * replayed.
178  */
181  (char *) page, true);
183  SPGIST_METAPAGE_BLKNO, page, true);
184 
185  /* Likewise for the root page. */
187 
190  (char *) page, true);
192  SPGIST_ROOT_BLKNO, page, true);
193 
194  /* Likewise for the null-tuples root page. */
196 
199  (char *) page, true);
201  SPGIST_NULL_BLKNO, page, true);
202 
203  /*
204  * An immediate sync is required even if we xlog'd the pages, because the
205  * writes did not go through shared buffers and therefore a concurrent
206  * checkpoint may have moved the redo pointer past our xlog record.
207  */
209 }
struct SMgrRelationData * rd_smgr
Definition: rel.h:57
#define SPGIST_NULLS
#define SPGIST_ROOT_BLKNO
RelFileNodeBackend smgr_rnode
Definition: smgr.h:43
#define SPGIST_NULL_BLKNO
void smgrwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync)
Definition: smgr.c:647
#define SPGIST_METAPAGE_BLKNO
RelFileNode node
Definition: relfilenode.h:74
void SpGistInitMetapage(Page page)
Definition: spgutils.c:554
void PageSetChecksumInplace(Page page, BlockNumber blkno)
Definition: bufpage.c:1195
void SpGistInitPage(Page page, uint16 f)
Definition: spgutils.c:529
void * palloc(Size size)
Definition: mcxt.c:924
XLogRecPtr log_newpage(RelFileNode *rnode, ForkNumber forkNum, BlockNumber blkno, Page page, bool page_std)
Definition: xloginsert.c:972
#define SPGIST_LEAF
void smgrimmedsync(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:734
Pointer Page
Definition: bufpage.h:74

◆ spgbulkdelete()

IndexBulkDeleteResult* spgbulkdelete ( IndexVacuumInfo info,
IndexBulkDeleteResult stats,
IndexBulkDeleteCallback  callback,
void *  callback_state 
)

Definition at line 901 of file spgvacuum.c.

References spgBulkDeleteState::callback, callback(), spgBulkDeleteState::callback_state, spgBulkDeleteState::info, palloc0(), spgvacuumscan(), and spgBulkDeleteState::stats.

Referenced by spghandler().

903 {
904  spgBulkDeleteState bds;
905 
906  /* allocate stats if first time through, else re-use existing struct */
907  if (stats == NULL)
909  bds.info = info;
910  bds.stats = stats;
911  bds.callback = callback;
912  bds.callback_state = callback_state;
913 
914  spgvacuumscan(&bds);
915 
916  return stats;
917 }
IndexVacuumInfo * info
Definition: spgvacuum.c:44
static void spgvacuumscan(spgBulkDeleteState *bds)
Definition: spgvacuum.c:790
static void callback(struct sockaddr *addr, struct sockaddr *mask, void *unused)
Definition: test_ifaddrs.c:48
IndexBulkDeleteCallback callback
Definition: spgvacuum.c:46
void * palloc0(Size size)
Definition: mcxt.c:955
void * callback_state
Definition: spgvacuum.c:47
IndexBulkDeleteResult * stats
Definition: spgvacuum.c:45

◆ spgcanreturn()

bool spgcanreturn ( Relation  index,
int  attno 
)

Definition at line 655 of file spgscan.c.

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

Referenced by spghandler().

656 {
657  SpGistCache *cache;
658 
659  /* We can do it if the opclass config function says so */
660  cache = spgGetCache(index);
661 
662  return cache->config.canReturnData;
663 }
SpGistCache * spgGetCache(Relation index)
Definition: spgutils.c:93
bool canReturnData
Definition: spgist.h:50
spgConfigOut config

◆ spgendscan()

void spgendscan ( IndexScanDesc  scan)

Definition at line 233 of file spgscan.c.

References MemoryContextDelete(), IndexScanDescData::opaque, SpGistScanOpaqueData::tempCxt, and SpGistScanOpaqueData::traversalCxt.

Referenced by spghandler().

234 {
236 
239 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
MemoryContext tempCxt
SpGistScanOpaqueData * SpGistScanOpaque
MemoryContext traversalCxt

◆ spggetbitmap()

int64 spggetbitmap ( IndexScanDesc  scan,
TIDBitmap tbm 
)

Definition at line 575 of file spgscan.c.

References IndexScanDescData::indexRelation, SpGistScanOpaqueData::ntids, IndexScanDescData::opaque, spgWalk(), storeBitmap(), SpGistScanOpaqueData::tbm, SpGistScanOpaqueData::want_itup, and IndexScanDescData::xs_snapshot.

Referenced by spghandler().

576 {
578 
579  /* Copy want_itup to *so so we don't need to pass it around separately */
580  so->want_itup = false;
581 
582  so->tbm = tbm;
583  so->ntids = 0;
584 
585  spgWalk(scan->indexRelation, so, true, storeBitmap, scan->xs_snapshot);
586 
587  return so->ntids;
588 }
Snapshot xs_snapshot
Definition: relscan.h:92
Relation indexRelation
Definition: relscan.h:91
SpGistScanOpaqueData * SpGistScanOpaque
static void spgWalk(Relation index, SpGistScanOpaque so, bool scanWholeIndex, storeRes_func storeRes, Snapshot snapshot)
Definition: spgscan.c:308
static void storeBitmap(SpGistScanOpaque so, ItemPointer heapPtr, Datum leafValue, bool isnull, bool recheck)
Definition: spgscan.c:567

◆ spggettuple()

bool spggettuple ( IndexScanDesc  scan,
ScanDirection  dir 
)

Definition at line 612 of file spgscan.c.

References elog, ERROR, ForwardScanDirection, SpGistScanOpaqueData::heapPtrs, i, IndexScanDescData::indexRelation, SpGistScanOpaqueData::iPtr, SpGistScanOpaqueData::nPtrs, IndexScanDescData::opaque, pfree(), SpGistScanOpaqueData::recheck, SpGistScanOpaqueData::reconTups, spgWalk(), storeGettuple(), HeapTupleData::t_self, SpGistScanOpaqueData::want_itup, IndexScanDescData::xs_ctup, IndexScanDescData::xs_hitup, IndexScanDescData::xs_recheck, IndexScanDescData::xs_snapshot, and IndexScanDescData::xs_want_itup.

Referenced by spghandler().

613 {
615 
616  if (dir != ForwardScanDirection)
617  elog(ERROR, "SP-GiST only supports forward scan direction");
618 
619  /* Copy want_itup to *so so we don't need to pass it around separately */
620  so->want_itup = scan->xs_want_itup;
621 
622  for (;;)
623  {
624  if (so->iPtr < so->nPtrs)
625  {
626  /* continuing to return tuples from a leaf page */
627  scan->xs_ctup.t_self = so->heapPtrs[so->iPtr];
628  scan->xs_recheck = so->recheck[so->iPtr];
629  scan->xs_hitup = so->reconTups[so->iPtr];
630  so->iPtr++;
631  return true;
632  }
633 
634  if (so->want_itup)
635  {
636  /* Must pfree reconstructed tuples to avoid memory leak */
637  int i;
638 
639  for (i = 0; i < so->nPtrs; i++)
640  pfree(so->reconTups[i]);
641  }
642  so->iPtr = so->nPtrs = 0;
643 
644  spgWalk(scan->indexRelation, so, false, storeGettuple,
645  scan->xs_snapshot);
646 
647  if (so->nPtrs == 0)
648  break; /* must have completed scan */
649  }
650 
651  return false;
652 }
ItemPointerData heapPtrs[MaxIndexTuplesPerPage]
Snapshot xs_snapshot
Definition: relscan.h:92
HeapTuple reconTups[MaxIndexTuplesPerPage]
Relation indexRelation
Definition: relscan.h:91
void pfree(void *pointer)
Definition: mcxt.c:1031
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
bool recheck[MaxIndexTuplesPerPage]
static void storeGettuple(SpGistScanOpaque so, ItemPointer heapPtr, Datum leafValue, bool isnull, bool recheck)
Definition: spgscan.c:592
SpGistScanOpaqueData * SpGistScanOpaque
static void spgWalk(Relation index, SpGistScanOpaque so, bool scanWholeIndex, storeRes_func storeRes, Snapshot snapshot)
Definition: spgscan.c:308
bool xs_want_itup
Definition: relscan.h:97
HeapTupleData xs_ctup
Definition: relscan.h:121
HeapTuple xs_hitup
Definition: relscan.h:117
int i
#define elog
Definition: elog.h:219

◆ spginsert()

bool spginsert ( Relation  index,
Datum values,
bool isnull,
ItemPointer  ht_ctid,
Relation  heapRel,
IndexUniqueCheck  checkUnique,
struct IndexInfo indexInfo 
)

Definition at line 215 of file spginsert.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, CurrentMemoryContext, initSpGistState(), MemoryContextDelete(), MemoryContextReset(), MemoryContextSwitchTo(), spgdoinsert(), and SpGistUpdateMetaPage().

Referenced by spghandler().

219 {
220  SpGistState spgstate;
221  MemoryContext oldCtx;
222  MemoryContext insertCtx;
223 
225  "SP-GiST insert temporary context",
227  oldCtx = MemoryContextSwitchTo(insertCtx);
228 
229  initSpGistState(&spgstate, index);
230 
231  /*
232  * We might have to repeat spgdoinsert() multiple times, if conflicts
233  * occur with concurrent insertions. If so, reset the insertCtx each time
234  * to avoid cumulative memory consumption. That means we also have to
235  * redo initSpGistState(), but it's cheap enough not to matter.
236  */
237  while (!spgdoinsert(index, &spgstate, ht_ctid, *values, *isnull))
238  {
239  MemoryContextReset(insertCtx);
240  initSpGistState(&spgstate, index);
241  }
242 
243  SpGistUpdateMetaPage(index);
244 
245  MemoryContextSwitchTo(oldCtx);
246  MemoryContextDelete(insertCtx);
247 
248  /* return false since we've not done any unique check */
249  return false;
250 }
void SpGistUpdateMetaPage(Relation index)
Definition: spgutils.c:270
bool spgdoinsert(Relation index, SpGistState *state, ItemPointer heapPtr, Datum datum, bool isnull)
Definition: spgdoinsert.c:1891
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:136
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
void initSpGistState(SpGistState *state, Relation index)
Definition: spgutils.c:175
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:170
static Datum values[MAXATTR]
Definition: bootstrap.c:164

◆ spgoptions()

bytea* spgoptions ( Datum  reloptions,
bool  validate 
)

Definition at line 581 of file spgutils.c.

References default_reloptions(), and RELOPT_KIND_SPGIST.

Referenced by spghandler().

582 {
583  return default_reloptions(reloptions, validate, RELOPT_KIND_SPGIST);
584 }
bytea * default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
Definition: reloptions.c:1343

◆ spgrescan()

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

Definition at line 210 of file spgscan.c.

References IndexScanDescData::keyData, memmove, MemoryContextReset(), IndexScanDescData::numberOfKeys, IndexScanDescData::opaque, resetSpGistScanOpaque(), spgPrepareScanKeys(), and SpGistScanOpaqueData::traversalCxt.

Referenced by spghandler().

212 {
214 
215  /* clear traversal context before proceeding to the next scan */
217 
218  /* copy scankeys into local storage */
219  if (scankey && scan->numberOfKeys > 0)
220  {
221  memmove(scan->keyData, scankey,
222  scan->numberOfKeys * sizeof(ScanKeyData));
223  }
224 
225  /* preprocess scankeys, set up the representation in *so */
226  spgPrepareScanKeys(scan);
227 
228  /* set up starting stack entries */
230 }
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:136
#define memmove(d, s, c)
Definition: c.h:1135
static void spgPrepareScanKeys(IndexScanDesc scan)
Definition: spgscan.c:116
SpGistScanOpaqueData * SpGistScanOpaque
ScanKey keyData
Definition: relscan.h:95
static void resetSpGistScanOpaque(SpGistScanOpaque so)
Definition: spgscan.c:71
MemoryContext traversalCxt

◆ spgvacuumcleanup()

IndexBulkDeleteResult* spgvacuumcleanup ( IndexVacuumInfo info,
IndexBulkDeleteResult stats 
)

Definition at line 932 of file spgvacuum.c.

References IndexVacuumInfo::analyze_only, spgBulkDeleteState::callback, spgBulkDeleteState::callback_state, dummy_callback(), IndexVacuumInfo::estimated_count, spgBulkDeleteState::info, IndexVacuumInfo::num_heap_tuples, IndexBulkDeleteResult::num_index_tuples, palloc0(), spgvacuumscan(), and spgBulkDeleteState::stats.

Referenced by spghandler().

933 {
934  spgBulkDeleteState bds;
935 
936  /* No-op in ANALYZE ONLY mode */
937  if (info->analyze_only)
938  return stats;
939 
940  /*
941  * We don't need to scan the index if there was a preceding bulkdelete
942  * pass. Otherwise, make a pass that won't delete any live tuples, but
943  * might still accomplish useful stuff with redirect/placeholder cleanup
944  * and/or FSM housekeeping, and in any case will provide stats.
945  */
946  if (stats == NULL)
947  {
949  bds.info = info;
950  bds.stats = stats;
951  bds.callback = dummy_callback;
952  bds.callback_state = NULL;
953 
954  spgvacuumscan(&bds);
955  }
956 
957  /*
958  * It's quite possible for us to be fooled by concurrent tuple moves into
959  * double-counting some index tuples, so disbelieve any total that exceeds
960  * the underlying heap's count ... if we know that accurately. Otherwise
961  * this might just make matters worse.
962  */
963  if (!info->estimated_count)
964  {
965  if (stats->num_index_tuples > info->num_heap_tuples)
966  stats->num_index_tuples = info->num_heap_tuples;
967  }
968 
969  return stats;
970 }
IndexVacuumInfo * info
Definition: spgvacuum.c:44
bool analyze_only
Definition: genam.h:47
static void spgvacuumscan(spgBulkDeleteState *bds)
Definition: spgvacuum.c:790
IndexBulkDeleteCallback callback
Definition: spgvacuum.c:46
void * palloc0(Size size)
Definition: mcxt.c:955
static bool dummy_callback(ItemPointer itemptr, void *state)
Definition: spgvacuum.c:921
double num_heap_tuples
Definition: genam.h:50
void * callback_state
Definition: spgvacuum.c:47
IndexBulkDeleteResult * stats
Definition: spgvacuum.c:45
double num_index_tuples
Definition: genam.h:76
bool estimated_count
Definition: genam.h:48

◆ spgvalidate()

bool spgvalidate ( Oid  opclassoid)

Definition at line 39 of file spgvalidate.c.

References AMOPSTRATEGY, AMPROCNUM, spgConfigIn::attType, check_amop_signature(), check_amproc_signature(), CLAOID, elog, ereport, errcode(), errmsg(), ERROR, format_operator(), format_procedure(), format_type_be(), OpFamilyOpFuncGroup::functionset, GETSTRUCT, HeapTupleIsValid, i, identify_opfamily_groups(), INFO, InvalidOid, spgConfigOut::leafType, OpFamilyOpFuncGroup::lefttype, lfirst, catclist::members, catclist::n_members, NameStr, ObjectIdGetDatum, OidFunctionCall2, OidIsValid, OpFamilyOpFuncGroup::operatorset, OPFAMILYOID, PointerGetDatum, ReleaseCatCacheList(), ReleaseSysCache(), OpFamilyOpFuncGroup::righttype, SearchSysCache1(), SearchSysCacheList1, SPGIST_CHOOSE_PROC, SPGIST_COMPRESS_PROC, SPGIST_CONFIG_PROC, SPGIST_INNER_CONSISTENT_PROC, SPGIST_LEAF_CONSISTENT_PROC, SPGIST_PICKSPLIT_PROC, SPGISTNProc, and catctup::tuple.

Referenced by spghandler().

40 {
41  bool result = true;
42  HeapTuple classtup;
43  Form_pg_opclass classform;
44  Oid opfamilyoid;
45  Oid opcintype;
46  char *opclassname;
47  HeapTuple familytup;
48  Form_pg_opfamily familyform;
49  char *opfamilyname;
50  CatCList *proclist,
51  *oprlist;
52  List *grouplist;
53  OpFamilyOpFuncGroup *opclassgroup;
54  int i;
55  ListCell *lc;
56  spgConfigIn configIn;
57  spgConfigOut configOut;
58  Oid configOutLefttype = InvalidOid;
59  Oid configOutRighttype = InvalidOid;
60 
61  /* Fetch opclass information */
62  classtup = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclassoid));
63  if (!HeapTupleIsValid(classtup))
64  elog(ERROR, "cache lookup failed for operator class %u", opclassoid);
65  classform = (Form_pg_opclass) GETSTRUCT(classtup);
66 
67  opfamilyoid = classform->opcfamily;
68  opcintype = classform->opcintype;
69  opclassname = NameStr(classform->opcname);
70 
71  /* Fetch opfamily information */
72  familytup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfamilyoid));
73  if (!HeapTupleIsValid(familytup))
74  elog(ERROR, "cache lookup failed for operator family %u", opfamilyoid);
75  familyform = (Form_pg_opfamily) GETSTRUCT(familytup);
76 
77  opfamilyname = NameStr(familyform->opfname);
78 
79  /* Fetch all operators and support functions of the opfamily */
80  oprlist = SearchSysCacheList1(AMOPSTRATEGY, ObjectIdGetDatum(opfamilyoid));
81  proclist = SearchSysCacheList1(AMPROCNUM, ObjectIdGetDatum(opfamilyoid));
82  grouplist = identify_opfamily_groups(oprlist, proclist);
83 
84  /* Check individual support functions */
85  for (i = 0; i < proclist->n_members; i++)
86  {
87  HeapTuple proctup = &proclist->members[i]->tuple;
88  Form_pg_amproc procform = (Form_pg_amproc) GETSTRUCT(proctup);
89  bool ok;
90 
91  /*
92  * All SP-GiST support functions should be registered with matching
93  * left/right types
94  */
95  if (procform->amproclefttype != procform->amprocrighttype)
96  {
97  ereport(INFO,
98  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
99  errmsg("operator family \"%s\" of access method %s contains support procedure %s with different left and right input types",
100  opfamilyname, "spgist",
101  format_procedure(procform->amproc))));
102  result = false;
103  }
104 
105  /* Check procedure numbers and function signatures */
106  switch (procform->amprocnum)
107  {
108  case SPGIST_CONFIG_PROC:
109  ok = check_amproc_signature(procform->amproc, VOIDOID, true,
110  2, 2, INTERNALOID, INTERNALOID);
111  configIn.attType = procform->amproclefttype;
112  memset(&configOut, 0, sizeof(configOut));
113 
114  OidFunctionCall2(procform->amproc,
115  PointerGetDatum(&configIn),
116  PointerGetDatum(&configOut));
117 
118  configOutLefttype = procform->amproclefttype;
119  configOutRighttype = procform->amprocrighttype;
120 
121  /*
122  * When leaf and attribute types are the same, compress
123  * function is not required and we set corresponding bit in
124  * functionset for later group consistency check.
125  */
126  if (!OidIsValid(configOut.leafType) ||
127  configOut.leafType == configIn.attType)
128  {
129  foreach(lc, grouplist)
130  {
131  OpFamilyOpFuncGroup *group = lfirst(lc);
132 
133  if (group->lefttype == procform->amproclefttype &&
134  group->righttype == procform->amprocrighttype)
135  {
136  group->functionset |=
137  ((uint64) 1) << SPGIST_COMPRESS_PROC;
138  break;
139  }
140  }
141  }
142  break;
143  case SPGIST_CHOOSE_PROC:
146  ok = check_amproc_signature(procform->amproc, VOIDOID, true,
147  2, 2, INTERNALOID, INTERNALOID);
148  break;
150  ok = check_amproc_signature(procform->amproc, BOOLOID, true,
151  2, 2, INTERNALOID, INTERNALOID);
152  break;
154  if (configOutLefttype != procform->amproclefttype ||
155  configOutRighttype != procform->amprocrighttype)
156  ok = false;
157  else
158  ok = check_amproc_signature(procform->amproc,
159  configOut.leafType, true,
160  1, 1, procform->amproclefttype);
161  break;
162  default:
163  ereport(INFO,
164  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
165  errmsg("operator family \"%s\" of access method %s contains function %s with invalid support number %d",
166  opfamilyname, "spgist",
167  format_procedure(procform->amproc),
168  procform->amprocnum)));
169  result = false;
170  continue; /* don't want additional message */
171  }
172 
173  if (!ok)
174  {
175  ereport(INFO,
176  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
177  errmsg("operator family \"%s\" of access method %s contains function %s with wrong signature for support number %d",
178  opfamilyname, "spgist",
179  format_procedure(procform->amproc),
180  procform->amprocnum)));
181  result = false;
182  }
183  }
184 
185  /* Check individual operators */
186  for (i = 0; i < oprlist->n_members; i++)
187  {
188  HeapTuple oprtup = &oprlist->members[i]->tuple;
189  Form_pg_amop oprform = (Form_pg_amop) GETSTRUCT(oprtup);
190 
191  /* TODO: Check that only allowed strategy numbers exist */
192  if (oprform->amopstrategy < 1 || oprform->amopstrategy > 63)
193  {
194  ereport(INFO,
195  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
196  errmsg("operator family \"%s\" of access method %s contains operator %s with invalid strategy number %d",
197  opfamilyname, "spgist",
198  format_operator(oprform->amopopr),
199  oprform->amopstrategy)));
200  result = false;
201  }
202 
203  /* spgist doesn't support ORDER BY operators */
204  if (oprform->amoppurpose != AMOP_SEARCH ||
205  OidIsValid(oprform->amopsortfamily))
206  {
207  ereport(INFO,
208  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
209  errmsg("operator family \"%s\" of access method %s contains invalid ORDER BY specification for operator %s",
210  opfamilyname, "spgist",
211  format_operator(oprform->amopopr))));
212  result = false;
213  }
214 
215  /* Check operator signature --- same for all spgist strategies */
216  if (!check_amop_signature(oprform->amopopr, BOOLOID,
217  oprform->amoplefttype,
218  oprform->amoprighttype))
219  {
220  ereport(INFO,
221  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
222  errmsg("operator family \"%s\" of access method %s contains operator %s with wrong signature",
223  opfamilyname, "spgist",
224  format_operator(oprform->amopopr))));
225  result = false;
226  }
227  }
228 
229  /* Now check for inconsistent groups of operators/functions */
230  opclassgroup = NULL;
231  foreach(lc, grouplist)
232  {
233  OpFamilyOpFuncGroup *thisgroup = (OpFamilyOpFuncGroup *) lfirst(lc);
234 
235  /* Remember the group exactly matching the test opclass */
236  if (thisgroup->lefttype == opcintype &&
237  thisgroup->righttype == opcintype)
238  opclassgroup = thisgroup;
239 
240  /*
241  * Complain if there are any datatype pairs with functions but no
242  * operators. This is about the best we can do for now to detect
243  * missing operators.
244  */
245  if (thisgroup->operatorset == 0)
246  {
247  ereport(INFO,
248  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
249  errmsg("operator family \"%s\" of access method %s is missing operator(s) for types %s and %s",
250  opfamilyname, "spgist",
251  format_type_be(thisgroup->lefttype),
252  format_type_be(thisgroup->righttype))));
253  result = false;
254  }
255 
256  /*
257  * Complain if we're missing functions for any datatype, remembering
258  * that SP-GiST doesn't use cross-type support functions.
259  */
260  if (thisgroup->lefttype != thisgroup->righttype)
261  continue;
262 
263  for (i = 1; i <= SPGISTNProc; i++)
264  {
265  if ((thisgroup->functionset & (((uint64) 1) << i)) != 0)
266  continue; /* got it */
267  ereport(INFO,
268  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
269  errmsg("operator family \"%s\" of access method %s is missing support function %d for type %s",
270  opfamilyname, "spgist", i,
271  format_type_be(thisgroup->lefttype))));
272  result = false;
273  }
274  }
275 
276  /* Check that the originally-named opclass is supported */
277  /* (if group is there, we already checked it adequately above) */
278  if (!opclassgroup)
279  {
280  ereport(INFO,
281  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
282  errmsg("operator class \"%s\" of access method %s is missing operator(s)",
283  opclassname, "spgist")));
284  result = false;
285  }
286 
287  ReleaseCatCacheList(proclist);
288  ReleaseCatCacheList(oprlist);
289  ReleaseSysCache(familytup);
290  ReleaseSysCache(classtup);
291 
292  return result;
293 }
int n_members
Definition: catcache.h:176
#define GETSTRUCT(TUP)
Definition: htup_details.h:668
#define SPGIST_LEAF_CONSISTENT_PROC
Definition: spgist.h:32
#define PointerGetDatum(X)
Definition: postgres.h:541
FormData_pg_amproc * Form_pg_amproc
Definition: pg_amproc.h:66
int errcode(int sqlerrcode)
Definition: elog.c:575
#define INFO
Definition: elog.h:33
char * format_type_be(Oid type_oid)
Definition: format_type.c:328
char * format_operator(Oid operator_oid)
Definition: regproc.c:820
Oid attType
Definition: spgist.h:42
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:605
void ReleaseCatCacheList(CatCList *list)
Definition: catcache.c:1800
CatCTup * members[FLEXIBLE_ARRAY_MEMBER]
Definition: catcache.h:178
bool check_amproc_signature(Oid funcid, Oid restype, bool exact, int minargs, int maxargs,...)
Definition: amvalidate.c:150
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
List * identify_opfamily_groups(CatCList *oprlist, CatCList *proclist)
Definition: amvalidate.c:41
#define SearchSysCacheList1(cacheId, key1)
Definition: syscache.h:209
#define ereport(elevel, rest)
Definition: elog.h:122
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
FormData_pg_opfamily * Form_pg_opfamily
Definition: pg_opfamily.h:49
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define InvalidOid
Definition: postgres_ext.h:36
char * format_procedure(Oid procedure_oid)
Definition: regproc.c:323
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define lfirst(lc)
Definition: pg_list.h:106
#define SPGIST_COMPRESS_PROC
Definition: spgist.h:33
#define SPGIST_CONFIG_PROC
Definition: spgist.h:28
bool check_amop_signature(Oid opno, Oid restype, Oid lefttype, Oid righttype)
Definition: amvalidate.c:194
#define OidFunctionCall2(functionId, arg1, arg2)
Definition: fmgr.h:630
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define SPGISTNProc
Definition: spgist.h:35
FormData_pg_amop * Form_pg_amop
Definition: pg_amop.h:86
int i
#define NameStr(name)
Definition: c.h:576
Oid leafType
Definition: spgist.h:49
#define SPGIST_INNER_CONSISTENT_PROC
Definition: spgist.h:31
HeapTupleData tuple
Definition: catcache.h:121
#define elog
Definition: elog.h:219
#define SPGIST_CHOOSE_PROC
Definition: spgist.h:29
FormData_pg_opclass * Form_pg_opclass
Definition: pg_opclass.h:81
#define SPGIST_PICKSPLIT_PROC
Definition: spgist.h:30
Definition: pg_list.h:45