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, 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",
197 
198  /* Set up indexTupDesc and xs_hitupdesc in case it's an index-only scan */
199  so->indexTupDesc = scan->xs_hitupdesc = RelationGetDescr(rel);
200 
201  scan->opaque = so;
202 
203  return scan;
204 }
#define RelationGetDescr(relation)
Definition: rel.h:437
MemoryContext tempCxt
TupleDesc xs_hitupdesc
Definition: relscan.h:118
Relation indexRelation
Definition: relscan.h:91
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:197
ScanKeyData * ScanKey
Definition: skey.h:75
void initSpGistState(SpGistState *state, Relation index)
Definition: spgutils.c:174
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:165
void * palloc0(Size size)
Definition: mcxt.c:864
SpGistScanOpaqueData * SpGistScanOpaque
void * palloc(Size size)
Definition: mcxt.c:835
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 70 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(), initSpGistState(), SpGistState::isBuild, MarkBufferDirty(), MemoryContextDelete(), PageSetLSN, palloc0(), REGBUF_STANDARD, REGBUF_WILL_INIT, 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, XLogBeginInsert(), XLogInsert(), and XLogRegisterBuffer().

Referenced by spghandler().

71 {
72  IndexBuildResult *result;
73  double reltuples;
74  SpGistBuildState buildstate;
75  Buffer metabuffer,
76  rootbuffer,
77  nullbuffer;
78 
79  if (RelationGetNumberOfBlocks(index) != 0)
80  elog(ERROR, "index \"%s\" already contains data",
82 
83  /*
84  * Initialize the meta page and root pages
85  */
86  metabuffer = SpGistNewBuffer(index);
87  rootbuffer = SpGistNewBuffer(index);
88  nullbuffer = SpGistNewBuffer(index);
89 
93 
95 
96  SpGistInitMetapage(BufferGetPage(metabuffer));
97  MarkBufferDirty(metabuffer);
98  SpGistInitBuffer(rootbuffer, SPGIST_LEAF);
99  MarkBufferDirty(rootbuffer);
101  MarkBufferDirty(nullbuffer);
102 
103  if (RelationNeedsWAL(index))
104  {
105  XLogRecPtr recptr;
106 
107  XLogBeginInsert();
108 
109  /*
110  * Replay will re-initialize the pages, so don't take full pages
111  * images. No other data to log.
112  */
116 
117  recptr = XLogInsert(RM_SPGIST_ID, XLOG_SPGIST_CREATE_INDEX);
118 
119  PageSetLSN(BufferGetPage(metabuffer), recptr);
120  PageSetLSN(BufferGetPage(rootbuffer), recptr);
121  PageSetLSN(BufferGetPage(nullbuffer), recptr);
122  }
123 
125 
126  UnlockReleaseBuffer(metabuffer);
127  UnlockReleaseBuffer(rootbuffer);
128  UnlockReleaseBuffer(nullbuffer);
129 
130  /*
131  * Now insert all the heap data into the index
132  */
133  initSpGistState(&buildstate.spgstate, index);
134  buildstate.spgstate.isBuild = true;
135 
137  "SP-GiST build temporary context",
139 
140  reltuples = IndexBuildHeapScan(heap, index, indexInfo, true,
141  spgistBuildCallback, (void *) &buildstate,
142  NULL);
143 
144  MemoryContextDelete(buildstate.tmpCtx);
145 
146  SpGistUpdateMetaPage(index);
147 
148  result = (IndexBuildResult *) palloc0(sizeof(IndexBuildResult));
149  result->heap_tuples = result->index_tuples = reltuples;
150 
151  return result;
152 }
void SpGistUpdateMetaPage(Relation index)
Definition: spgutils.c:269
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:198
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:2411
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:197
#define SPGIST_NULL_BLKNO
#define REGBUF_STANDARD
Definition: xloginsert.h:34
#define SPGIST_METAPAGE_BLKNO
void initSpGistState(SpGistState *state, Relation index)
Definition: spgutils.c:174
#define RelationGetRelationName(relation)
Definition: rel.h:445
static void spgistBuildCallback(Relation index, HeapTuple htup, Datum *values, bool *isnull, bool tupleIsAlive, void *state)
Definition: spginsert.c:41
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
void SpGistInitBuffer(Buffer b, uint16 f)
Definition: spgutils.c:543
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:165
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
void * palloc0(Size size)
Definition: mcxt.c:864
#define RelationGetNumberOfBlocks(reln)
Definition: bufmgr.h:199
Buffer SpGistNewBuffer(Relation index)
Definition: spgutils.c:204
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:688
void SpGistInitMetapage(Page page)
Definition: spgutils.c:553
#define RelationNeedsWAL(relation)
Definition: rel.h:514
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2605
MemoryContext tmpCtx
Definition: spginsert.c:35
#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
double index_tuples
Definition: genam.h:33
double heap_tuples
Definition: genam.h:32

◆ spgbuildempty()

void spgbuildempty ( Relation  index)

Definition at line 158 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().

159 {
160  Page page;
161 
162  /* Construct metapage. */
163  page = (Page) palloc(BLCKSZ);
164  SpGistInitMetapage(page);
165 
166  /*
167  * Write the page and log it unconditionally. This is important
168  * particularly for indexes created on tablespaces and databases whose
169  * creation happened after the last redo pointer as recovery removes any
170  * of their existing content when the corresponding create records are
171  * replayed.
172  */
175  (char *) page, true);
177  SPGIST_METAPAGE_BLKNO, page, true);
178 
179  /* Likewise for the root page. */
181 
184  (char *) page, true);
186  SPGIST_ROOT_BLKNO, page, true);
187 
188  /* Likewise for the null-tuples root page. */
190 
193  (char *) page, true);
195  SPGIST_NULL_BLKNO, page, true);
196 
197  /*
198  * An immediate sync is required even if we xlog'd the pages, because the
199  * writes did not go through shared buffers and therefore a concurrent
200  * checkpoint may have moved the redo pointer past our xlog record.
201  */
203 }
struct SMgrRelationData * rd_smgr
Definition: rel.h:87
#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:553
void PageSetChecksumInplace(Page page, BlockNumber blkno)
Definition: bufpage.c:1195
void SpGistInitPage(Page page, uint16 f)
Definition: spgutils.c:528
void * palloc(Size size)
Definition: mcxt.c:835
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 886 of file spgvacuum.c.

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

Referenced by spghandler().

888 {
889  spgBulkDeleteState bds;
890 
891  /* allocate stats if first time through, else re-use existing struct */
892  if (stats == NULL)
894  bds.info = info;
895  bds.stats = stats;
896  bds.callback = callback;
897  bds.callback_state = callback_state;
898 
899  spgvacuumscan(&bds);
900 
901  return stats;
902 }
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:864
void * callback_state
Definition: spgvacuum.c:47
IndexBulkDeleteResult * stats
Definition: spgvacuum.c:45

◆ spgcanreturn()

bool spgcanreturn ( Relation  index,
int  attno 
)

Definition at line 648 of file spgscan.c.

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

Referenced by spghandler().

649 {
650  SpGistCache *cache;
651 
652  /* We can do it if the opclass config function says so */
653  cache = spgGetCache(index);
654 
655  return cache->config.canReturnData;
656 }
SpGistCache * spgGetCache(Relation index)
Definition: spgutils.c:92
bool canReturnData
Definition: spgist.h:50
spgConfigOut config

◆ spgendscan()

void spgendscan ( IndexScanDesc  scan)

Definition at line 227 of file spgscan.c.

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

Referenced by spghandler().

228 {
230 
232 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:198
MemoryContext tempCxt
SpGistScanOpaqueData * SpGistScanOpaque

◆ spggetbitmap()

int64 spggetbitmap ( IndexScanDesc  scan,
TIDBitmap tbm 
)

Definition at line 568 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().

569 {
571 
572  /* Copy want_itup to *so so we don't need to pass it around separately */
573  so->want_itup = false;
574 
575  so->tbm = tbm;
576  so->ntids = 0;
577 
578  spgWalk(scan->indexRelation, so, true, storeBitmap, scan->xs_snapshot);
579 
580  return so->ntids;
581 }
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:301
static void storeBitmap(SpGistScanOpaque so, ItemPointer heapPtr, Datum leafValue, bool isnull, bool recheck)
Definition: spgscan.c:560

◆ spggettuple()

bool spggettuple ( IndexScanDesc  scan,
ScanDirection  dir 
)

Definition at line 605 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().

606 {
608 
609  if (dir != ForwardScanDirection)
610  elog(ERROR, "SP-GiST only supports forward scan direction");
611 
612  /* Copy want_itup to *so so we don't need to pass it around separately */
613  so->want_itup = scan->xs_want_itup;
614 
615  for (;;)
616  {
617  if (so->iPtr < so->nPtrs)
618  {
619  /* continuing to return tuples from a leaf page */
620  scan->xs_ctup.t_self = so->heapPtrs[so->iPtr];
621  scan->xs_recheck = so->recheck[so->iPtr];
622  scan->xs_hitup = so->reconTups[so->iPtr];
623  so->iPtr++;
624  return true;
625  }
626 
627  if (so->want_itup)
628  {
629  /* Must pfree reconstructed tuples to avoid memory leak */
630  int i;
631 
632  for (i = 0; i < so->nPtrs; i++)
633  pfree(so->reconTups[i]);
634  }
635  so->iPtr = so->nPtrs = 0;
636 
637  spgWalk(scan->indexRelation, so, false, storeGettuple,
638  scan->xs_snapshot);
639 
640  if (so->nPtrs == 0)
641  break; /* must have completed scan */
642  }
643 
644  return false;
645 }
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:936
#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:585
SpGistScanOpaqueData * SpGistScanOpaque
static void spgWalk(Relation index, SpGistScanOpaque so, bool scanWholeIndex, storeRes_func storeRes, Snapshot snapshot)
Definition: spgscan.c:301
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 209 of file spginsert.c.

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

Referenced by spghandler().

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

◆ spgoptions()

bytea* spgoptions ( Datum  reloptions,
bool  validate 
)

Definition at line 580 of file spgutils.c.

References default_reloptions(), and RELOPT_KIND_SPGIST.

Referenced by spghandler().

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

◆ spgrescan()

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

Definition at line 207 of file spgscan.c.

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

Referenced by spghandler().

209 {
211 
212  /* copy scankeys into local storage */
213  if (scankey && scan->numberOfKeys > 0)
214  {
215  memmove(scan->keyData, scankey,
216  scan->numberOfKeys * sizeof(ScanKeyData));
217  }
218 
219  /* preprocess scankeys, set up the representation in *so */
220  spgPrepareScanKeys(scan);
221 
222  /* set up starting stack entries */
224 }
#define memmove(d, s, c)
Definition: c.h:1089
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

◆ spgvacuumcleanup()

IndexBulkDeleteResult* spgvacuumcleanup ( IndexVacuumInfo info,
IndexBulkDeleteResult stats 
)

Definition at line 917 of file spgvacuum.c.

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

Referenced by spghandler().

918 {
919  Relation index = info->index;
920  spgBulkDeleteState bds;
921 
922  /* No-op in ANALYZE ONLY mode */
923  if (info->analyze_only)
924  return stats;
925 
926  /*
927  * We don't need to scan the index if there was a preceding bulkdelete
928  * pass. Otherwise, make a pass that won't delete any live tuples, but
929  * might still accomplish useful stuff with redirect/placeholder cleanup,
930  * and in any case will provide stats.
931  */
932  if (stats == NULL)
933  {
935  bds.info = info;
936  bds.stats = stats;
937  bds.callback = dummy_callback;
938  bds.callback_state = NULL;
939 
940  spgvacuumscan(&bds);
941  }
942 
943  /* Finally, vacuum the FSM */
945 
946  /*
947  * It's quite possible for us to be fooled by concurrent tuple moves into
948  * double-counting some index tuples, so disbelieve any total that exceeds
949  * the underlying heap's count ... if we know that accurately. Otherwise
950  * this might just make matters worse.
951  */
952  if (!info->estimated_count)
953  {
954  if (stats->num_index_tuples > info->num_heap_tuples)
955  stats->num_index_tuples = info->num_heap_tuples;
956  }
957 
958  return stats;
959 }
IndexVacuumInfo * info
Definition: spgvacuum.c:44
bool analyze_only
Definition: genam.h:47
Relation index
Definition: genam.h:46
Definition: type.h:89
static void spgvacuumscan(spgBulkDeleteState *bds)
Definition: spgvacuum.c:790
IndexBulkDeleteCallback callback
Definition: spgvacuum.c:46
void * palloc0(Size size)
Definition: mcxt.c:864
static bool dummy_callback(ItemPointer itemptr, void *state)
Definition: spgvacuum.c:906
double num_heap_tuples
Definition: genam.h:50
void * callback_state
Definition: spgvacuum.c:47
void IndexFreeSpaceMapVacuum(Relation rel)
Definition: indexfsm.c:71
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 AMOP_SEARCH, AMOPSTRATEGY, AMPROCNUM, spgConfigIn::attType, BOOLOID, 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, INTERNALOID, 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, catctup::tuple, and VOIDOID.

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 function
123  * is not required and we set corresponding bit in functionset
124  * 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:661
#define SPGIST_LEAF_CONSISTENT_PROC
Definition: spgist.h:32
#define AMOP_SEARCH
Definition: pg_amop.h:69
#define PointerGetDatum(X)
Definition: postgres.h:539
FormData_pg_amproc * Form_pg_amproc
Definition: pg_amproc.h:59
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:320
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:594
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 VOIDOID
Definition: pg_type.h:690
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#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:44
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define InvalidOid
Definition: postgres_ext.h:36
#define INTERNALOID
Definition: pg_type.h:698
char * format_procedure(Oid procedure_oid)
Definition: regproc.c:323
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#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 BOOLOID
Definition: pg_type.h:288
#define OidFunctionCall2(functionId, arg1, arg2)
Definition: fmgr.h:625
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:77
int i
#define NameStr(name)
Definition: c.h:565
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:68
#define SPGIST_PICKSPLIT_PROC
Definition: spgist.h:30
Definition: pg_list.h:45