PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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 SPGISTNProc   5
 

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

#define SPGIST_CHOOSE_PROC   2

Definition at line 29 of file spgist.h.

Referenced by spgdoinsert(), and spgvalidate().

#define SPGIST_CONFIG_PROC   1

Definition at line 28 of file spgist.h.

Referenced by spgGetCache(), and spgvalidate().

#define SPGIST_DEFAULT_FILLFACTOR   80

Definition at line 25 of file spgist.h.

Referenced by SpGistGetBuffer().

#define SPGIST_INNER_CONSISTENT_PROC   4

Definition at line 31 of file spgist.h.

Referenced by spgvalidate(), and spgWalk().

#define SPGIST_LEAF_CONSISTENT_PROC   5

Definition at line 32 of file spgist.h.

Referenced by spgLeafTest(), and spgvalidate().

#define SPGIST_MIN_FILLFACTOR   10

Definition at line 24 of file spgist.h.

#define SPGIST_PICKSPLIT_PROC   3

Definition at line 30 of file spgist.h.

Referenced by doPickSplit(), and spgvalidate().

#define SPGISTNProc   5

Definition at line 33 of file spgist.h.

Referenced by spghandler(), and spgvalidate().

Typedef Documentation

Enumeration Type Documentation

Enumerator
spgMatchNode 
spgAddNode 
spgSplitTuple 

Definition at line 68 of file spgist.h.

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

Function Documentation

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, NULL, 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:428
MemoryContext tempCxt
TupleDesc xs_hitupdesc
Definition: relscan.h:116
Relation indexRelation
Definition: relscan.h:89
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
ScanKeyData * ScanKey
Definition: skey.h:75
void initSpGistState(SpGistState *state, Relation index)
Definition: spgutils.c:158
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
void * palloc0(Size size)
Definition: mcxt.c:878
SpGistScanOpaqueData * SpGistScanOpaque
#define NULL
Definition: c.h:229
void * palloc(Size size)
Definition: mcxt.c:849
IndexScanDesc RelationGetIndexScan(Relation indexRelation, int nkeys, int norderbys)
Definition: genam.c:78
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, result, 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 {
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  */
113  XLogRegisterBuffer(0, metabuffer, REGBUF_WILL_INIT);
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 
143  MemoryContextDelete(buildstate.tmpCtx);
144 
145  SpGistUpdateMetaPage(index);
146 
147  result = (IndexBuildResult *) palloc0(sizeof(IndexBuildResult));
148  result->heap_tuples = result->index_tuples = reltuples;
149 
150  return result;
151 }
void SpGistUpdateMetaPage(Relation index)
Definition: spgutils.c:252
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
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
return result
Definition: formatting.c:1633
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
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
#define SPGIST_NULL_BLKNO
#define REGBUF_STANDARD
Definition: xloginsert.h:34
#define SPGIST_METAPAGE_BLKNO
void initSpGistState(SpGistState *state, Relation index)
Definition: spgutils.c:158
#define RelationGetRelationName(relation)
Definition: rel.h:436
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:514
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
void * palloc0(Size size)
Definition: mcxt.c:878
#define RelationGetNumberOfBlocks(reln)
Definition: bufmgr.h:199
Buffer SpGistNewBuffer(Relation index)
Definition: spgutils.c:187
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:675
void SpGistInitMetapage(Page page)
Definition: spgutils.c:524
#define RelationNeedsWAL(relation)
Definition: rel.h:505
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2605
double IndexBuildHeapScan(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, bool allow_sync, IndexBuildCallback callback, void *callback_state)
Definition: index.c:2169
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
void spgbuildempty ( Relation  index)

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

158 {
159  Page page;
160 
161  /* Construct metapage. */
162  page = (Page) palloc(BLCKSZ);
163  SpGistInitMetapage(page);
164 
165  /*
166  * Write the page and log it unconditionally. This is important
167  * particularly for indexes created on tablespaces and databases whose
168  * creation happened after the last redo pointer as recovery removes any
169  * of their existing content when the corresponding create records are
170  * replayed.
171  */
174  (char *) page, true);
176  SPGIST_METAPAGE_BLKNO, page, false);
177 
178  /* Likewise for the root page. */
180 
183  (char *) page, true);
185  SPGIST_ROOT_BLKNO, page, true);
186 
187  /* Likewise for the null-tuples root page. */
189 
192  (char *) page, true);
194  SPGIST_NULL_BLKNO, page, true);
195 
196  /*
197  * An immediate sync is required even if we xlog'd the pages, because the
198  * writes did not go through shared buffers and therefore a concurrent
199  * checkpoint may have moved the redo pointer past our xlog record.
200  */
202 }
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:524
void PageSetChecksumInplace(Page page, BlockNumber blkno)
Definition: bufpage.c:1199
void SpGistInitPage(Page page, uint16 f)
Definition: spgutils.c:499
void * palloc(Size size)
Definition: mcxt.c:849
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
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, NULL, 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:878
void * callback_state
Definition: spgvacuum.c:47
#define NULL
Definition: c.h:229
IndexBulkDeleteResult * stats
Definition: spgvacuum.c:45
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:47
spgConfigOut config
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:200
MemoryContext tempCxt
SpGistScanOpaqueData * SpGistScanOpaque
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:90
Relation indexRelation
Definition: relscan.h:89
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
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:90
HeapTuple reconTups[MaxIndexTuplesPerPage]
Relation indexRelation
Definition: relscan.h:89
void pfree(void *pointer)
Definition: mcxt.c:950
#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:95
HeapTupleData xs_ctup
Definition: relscan.h:119
HeapTuple xs_hitup
Definition: relscan.h:115
int i
#define elog
Definition: elog.h:219
bool spginsert ( Relation  index,
Datum values,
bool isnull,
ItemPointer  ht_ctid,
Relation  heapRel,
IndexUniqueCheck  checkUnique,
struct IndexInfo indexInfo 
)

Definition at line 208 of file spginsert.c.

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

Referenced by spghandler().

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

Definition at line 543 of file spgutils.c.

References default_reloptions(), and RELOPT_KIND_SPGIST.

Referenced by spghandler().

544 {
545  return default_reloptions(reloptions, validate, RELOPT_KIND_SPGIST);
546 }
bytea * default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
Definition: reloptions.c:1316
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:1058
static void spgPrepareScanKeys(IndexScanDesc scan)
Definition: spgscan.c:116
SpGistScanOpaqueData * SpGistScanOpaque
ScanKey keyData
Definition: relscan.h:93
static void resetSpGistScanOpaque(SpGistScanOpaque so)
Definition: spgscan.c:71
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, NULL, 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:878
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
#define NULL
Definition: c.h:229
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
bool spgvalidate ( Oid  opclassoid)

Definition at line 38 of file spgvalidate.c.

References AMOP_SEARCH, AMOPSTRATEGY, AMPROCNUM, 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, OpFamilyOpFuncGroup::lefttype, lfirst, catclist::members, catclist::n_members, NameStr, NULL, ObjectIdGetDatum, OidIsValid, OpFamilyOpFuncGroup::operatorset, OPFAMILYOID, ReleaseCatCacheList(), ReleaseSysCache(), result, OpFamilyOpFuncGroup::righttype, SearchSysCache1, SearchSysCacheList1, SPGIST_CHOOSE_PROC, SPGIST_CONFIG_PROC, SPGIST_INNER_CONSISTENT_PROC, SPGIST_LEAF_CONSISTENT_PROC, SPGIST_PICKSPLIT_PROC, SPGISTNProc, catctup::tuple, and VOIDOID.

Referenced by spghandler().

39 {
40  bool result = true;
41  HeapTuple classtup;
42  Form_pg_opclass classform;
43  Oid opfamilyoid;
44  Oid opcintype;
45  char *opclassname;
46  HeapTuple familytup;
47  Form_pg_opfamily familyform;
48  char *opfamilyname;
49  CatCList *proclist,
50  *oprlist;
51  List *grouplist;
52  OpFamilyOpFuncGroup *opclassgroup;
53  int i;
54  ListCell *lc;
55 
56  /* Fetch opclass information */
57  classtup = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclassoid));
58  if (!HeapTupleIsValid(classtup))
59  elog(ERROR, "cache lookup failed for operator class %u", opclassoid);
60  classform = (Form_pg_opclass) GETSTRUCT(classtup);
61 
62  opfamilyoid = classform->opcfamily;
63  opcintype = classform->opcintype;
64  opclassname = NameStr(classform->opcname);
65 
66  /* Fetch opfamily information */
67  familytup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfamilyoid));
68  if (!HeapTupleIsValid(familytup))
69  elog(ERROR, "cache lookup failed for operator family %u", opfamilyoid);
70  familyform = (Form_pg_opfamily) GETSTRUCT(familytup);
71 
72  opfamilyname = NameStr(familyform->opfname);
73 
74  /* Fetch all operators and support functions of the opfamily */
75  oprlist = SearchSysCacheList1(AMOPSTRATEGY, ObjectIdGetDatum(opfamilyoid));
76  proclist = SearchSysCacheList1(AMPROCNUM, ObjectIdGetDatum(opfamilyoid));
77 
78  /* Check individual support functions */
79  for (i = 0; i < proclist->n_members; i++)
80  {
81  HeapTuple proctup = &proclist->members[i]->tuple;
82  Form_pg_amproc procform = (Form_pg_amproc) GETSTRUCT(proctup);
83  bool ok;
84 
85  /*
86  * All SP-GiST support functions should be registered with matching
87  * left/right types
88  */
89  if (procform->amproclefttype != procform->amprocrighttype)
90  {
91  ereport(INFO,
92  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
93  errmsg("operator family \"%s\" of access method %s contains support procedure %s with different left and right input types",
94  opfamilyname, "spgist",
95  format_procedure(procform->amproc))));
96  result = false;
97  }
98 
99  /* Check procedure numbers and function signatures */
100  switch (procform->amprocnum)
101  {
102  case SPGIST_CONFIG_PROC:
103  case SPGIST_CHOOSE_PROC:
106  ok = check_amproc_signature(procform->amproc, VOIDOID, true,
107  2, 2, INTERNALOID, INTERNALOID);
108  break;
110  ok = check_amproc_signature(procform->amproc, BOOLOID, true,
111  2, 2, INTERNALOID, INTERNALOID);
112  break;
113  default:
114  ereport(INFO,
115  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
116  errmsg("operator family \"%s\" of access method %s contains function %s with invalid support number %d",
117  opfamilyname, "spgist",
118  format_procedure(procform->amproc),
119  procform->amprocnum)));
120  result = false;
121  continue; /* don't want additional message */
122  }
123 
124  if (!ok)
125  {
126  ereport(INFO,
127  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
128  errmsg("operator family \"%s\" of access method %s contains function %s with wrong signature for support number %d",
129  opfamilyname, "spgist",
130  format_procedure(procform->amproc),
131  procform->amprocnum)));
132  result = false;
133  }
134  }
135 
136  /* Check individual operators */
137  for (i = 0; i < oprlist->n_members; i++)
138  {
139  HeapTuple oprtup = &oprlist->members[i]->tuple;
140  Form_pg_amop oprform = (Form_pg_amop) GETSTRUCT(oprtup);
141 
142  /* TODO: Check that only allowed strategy numbers exist */
143  if (oprform->amopstrategy < 1 || oprform->amopstrategy > 63)
144  {
145  ereport(INFO,
146  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
147  errmsg("operator family \"%s\" of access method %s contains operator %s with invalid strategy number %d",
148  opfamilyname, "spgist",
149  format_operator(oprform->amopopr),
150  oprform->amopstrategy)));
151  result = false;
152  }
153 
154  /* spgist doesn't support ORDER BY operators */
155  if (oprform->amoppurpose != AMOP_SEARCH ||
156  OidIsValid(oprform->amopsortfamily))
157  {
158  ereport(INFO,
159  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
160  errmsg("operator family \"%s\" of access method %s contains invalid ORDER BY specification for operator %s",
161  opfamilyname, "spgist",
162  format_operator(oprform->amopopr))));
163  result = false;
164  }
165 
166  /* Check operator signature --- same for all spgist strategies */
167  if (!check_amop_signature(oprform->amopopr, BOOLOID,
168  oprform->amoplefttype,
169  oprform->amoprighttype))
170  {
171  ereport(INFO,
172  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
173  errmsg("operator family \"%s\" of access method %s contains operator %s with wrong signature",
174  opfamilyname, "spgist",
175  format_operator(oprform->amopopr))));
176  result = false;
177  }
178  }
179 
180  /* Now check for inconsistent groups of operators/functions */
181  grouplist = identify_opfamily_groups(oprlist, proclist);
182  opclassgroup = NULL;
183  foreach(lc, grouplist)
184  {
185  OpFamilyOpFuncGroup *thisgroup = (OpFamilyOpFuncGroup *) lfirst(lc);
186 
187  /* Remember the group exactly matching the test opclass */
188  if (thisgroup->lefttype == opcintype &&
189  thisgroup->righttype == opcintype)
190  opclassgroup = thisgroup;
191 
192  /*
193  * Complain if there are any datatype pairs with functions but no
194  * operators. This is about the best we can do for now to detect
195  * missing operators.
196  */
197  if (thisgroup->operatorset == 0)
198  {
199  ereport(INFO,
200  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
201  errmsg("operator family \"%s\" of access method %s is missing operator(s) for types %s and %s",
202  opfamilyname, "spgist",
203  format_type_be(thisgroup->lefttype),
204  format_type_be(thisgroup->righttype))));
205  result = false;
206  }
207 
208  /*
209  * Complain if we're missing functions for any datatype, remembering
210  * that SP-GiST doesn't use cross-type support functions.
211  */
212  if (thisgroup->lefttype != thisgroup->righttype)
213  continue;
214 
215  for (i = 1; i <= SPGISTNProc; i++)
216  {
217  if ((thisgroup->functionset & (((uint64) 1) << i)) != 0)
218  continue; /* got it */
219  ereport(INFO,
220  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
221  errmsg("operator family \"%s\" of access method %s is missing support function %d for type %s",
222  opfamilyname, "spgist", i,
223  format_type_be(thisgroup->lefttype))));
224  result = false;
225  }
226  }
227 
228  /* Check that the originally-named opclass is supported */
229  /* (if group is there, we already checked it adequately above) */
230  if (!opclassgroup)
231  {
232  ereport(INFO,
233  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
234  errmsg("operator class \"%s\" of access method %s is missing operator(s)",
235  opclassname, "spgist")));
236  result = false;
237  }
238 
239  ReleaseCatCacheList(proclist);
240  ReleaseCatCacheList(oprlist);
241  ReleaseSysCache(familytup);
242  ReleaseSysCache(classtup);
243 
244  return result;
245 }
int n_members
Definition: catcache.h:154
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define SPGIST_LEAF_CONSISTENT_PROC
Definition: spgist.h:32
#define AMOP_SEARCH
Definition: pg_amop.h:69
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:94
return result
Definition: formatting.c:1633
char * format_operator(Oid operator_oid)
Definition: regproc.c:820
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:538
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
void ReleaseCatCacheList(CatCList *list)
Definition: catcache.c:1651
CatCTup * members[FLEXIBLE_ARRAY_MEMBER]
Definition: catcache.h:155
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:513
#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:201
#define ereport(elevel, rest)
Definition: elog.h:122
FormData_pg_opfamily * Form_pg_opfamily
Definition: pg_opfamily.h:44
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
#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 NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
#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
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define SPGISTNProc
Definition: spgist.h:33
FormData_pg_amop * Form_pg_amop
Definition: pg_amop.h:77
int i
#define NameStr(name)
Definition: c.h:499
#define SPGIST_INNER_CONSISTENT_PROC
Definition: spgist.h:31
HeapTupleData tuple
Definition: catcache.h:116
#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