PostgreSQL Source Code  git master
spgist.h File Reference
#include "access/amapi.h"
#include "access/xlogreader.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 28 of file spgist.h.

Referenced by spgdoinsert(), and spgvalidate().

◆ SPGIST_COMPRESS_PROC

#define SPGIST_COMPRESS_PROC   6

Definition at line 32 of file spgist.h.

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

◆ SPGIST_CONFIG_PROC

#define SPGIST_CONFIG_PROC   1

Definition at line 27 of file spgist.h.

Referenced by spgGetCache(), and spgvalidate().

◆ SPGIST_DEFAULT_FILLFACTOR

#define SPGIST_DEFAULT_FILLFACTOR   80

Definition at line 24 of file spgist.h.

Referenced by SpGistGetBuffer().

◆ SPGIST_INNER_CONSISTENT_PROC

#define SPGIST_INNER_CONSISTENT_PROC   4

Definition at line 30 of file spgist.h.

Referenced by spgbeginscan(), and spgvalidate().

◆ SPGIST_LEAF_CONSISTENT_PROC

#define SPGIST_LEAF_CONSISTENT_PROC   5

Definition at line 31 of file spgist.h.

Referenced by spgbeginscan(), and spgvalidate().

◆ SPGIST_MIN_FILLFACTOR

#define SPGIST_MIN_FILLFACTOR   10

Definition at line 23 of file spgist.h.

◆ SPGIST_PICKSPLIT_PROC

#define SPGIST_PICKSPLIT_PROC   3

Definition at line 29 of file spgist.h.

Referenced by doPickSplit(), and spgvalidate().

◆ SPGISTNProc

#define SPGISTNProc   6

Definition at line 34 of file spgist.h.

Referenced by spghandler(), and spgvalidate().

◆ SPGISTNRequiredProc

#define SPGISTNRequiredProc   5

Definition at line 33 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 70 of file spgist.h.

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

Function Documentation

◆ spgbeginscan()

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

Definition at line 267 of file spgscan.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, CurrentMemoryContext, fmgr_info_copy(), get_float8_infinity(), i, index_getprocinfo(), SpGistScanOpaqueData::indexCollation, IndexScanDescData::indexRelation, SpGistScanOpaqueData::indexTupDesc, SpGistScanOpaqueData::infDistances, initSpGistState(), SpGistScanOpaqueData::innerConsistentFn, SpGistScanOpaqueData::keyData, SpGistScanOpaqueData::leafConsistentFn, IndexScanDescData::numberOfOrderBys, IndexScanDescData::opaque, SpGistScanOpaqueData::orderByTypes, palloc(), palloc0(), RelationData::rd_indcollation, RelationGetDescr, RelationGetIndexScan(), SPGIST_INNER_CONSISTENT_PROC, SPGIST_LEAF_CONSISTENT_PROC, SpGistScanOpaqueData::state, SpGistScanOpaqueData::tempCxt, SpGistScanOpaqueData::traversalCxt, IndexScanDescData::xs_hitupdesc, IndexScanDescData::xs_orderbynulls, IndexScanDescData::xs_orderbyvals, and SpGistScanOpaqueData::zeroDistances.

Referenced by spghandler().

268 {
269  IndexScanDesc scan;
270  SpGistScanOpaque so;
271  int i;
272 
273  scan = RelationGetIndexScan(rel, keysz, orderbysz);
274 
276  if (keysz > 0)
277  so->keyData = (ScanKey) palloc(sizeof(ScanKeyData) * keysz);
278  else
279  so->keyData = NULL;
280  initSpGistState(&so->state, scan->indexRelation);
281 
283  "SP-GiST search temporary context",
286  "SP-GiST traversal-value context",
288 
289  /* Set up indexTupDesc and xs_hitupdesc in case it's an index-only scan */
290  so->indexTupDesc = scan->xs_hitupdesc = RelationGetDescr(rel);
291 
292  /* Allocate various arrays needed for order-by scans */
293  if (scan->numberOfOrderBys > 0)
294  {
295  /* This will be filled in spgrescan, but allocate the space here */
296  so->orderByTypes = (Oid *)
297  palloc(sizeof(Oid) * scan->numberOfOrderBys);
298 
299  /* These arrays have constant contents, so we can fill them now */
300  so->zeroDistances = (double *)
301  palloc(sizeof(double) * scan->numberOfOrderBys);
302  so->infDistances = (double *)
303  palloc(sizeof(double) * scan->numberOfOrderBys);
304 
305  for (i = 0; i < scan->numberOfOrderBys; i++)
306  {
307  so->zeroDistances[i] = 0.0;
309  }
310 
311  scan->xs_orderbyvals = (Datum *)
312  palloc0(sizeof(Datum) * scan->numberOfOrderBys);
313  scan->xs_orderbynulls = (bool *)
314  palloc(sizeof(bool) * scan->numberOfOrderBys);
315  memset(scan->xs_orderbynulls, true,
316  sizeof(bool) * scan->numberOfOrderBys);
317  }
318 
322 
326 
327  so->indexCollation = rel->rd_indcollation[0];
328 
329  scan->opaque = so;
330 
331  return scan;
332 }
#define AllocSetContextCreate
Definition: memutils.h:169
static float8 get_float8_infinity(void)
Definition: float.h:90
#define SPGIST_LEAF_CONSISTENT_PROC
Definition: spgist.h:31
FmgrInfo * index_getprocinfo(Relation irel, AttrNumber attnum, uint16 procnum)
Definition: indexam.c:794
#define RelationGetDescr(relation)
Definition: rel.h:442
struct TupleDescData * xs_hitupdesc
Definition: relscan.h:130
MemoryContext tempCxt
Datum * xs_orderbyvals
Definition: relscan.h:146
unsigned int Oid
Definition: postgres_ext.h:31
Relation indexRelation
Definition: relscan.h:103
bool * xs_orderbynulls
Definition: relscan.h:147
Oid * rd_indcollation
Definition: rel.h:168
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:191
void fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo, MemoryContext destcxt)
Definition: fmgr.c:610
ScanKeyData * ScanKey
Definition: skey.h:75
void initSpGistState(SpGistState *state, Relation index)
Definition: spgutils.c:181
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
void * palloc0(Size size)
Definition: mcxt.c:955
uintptr_t Datum
Definition: postgres.h:367
SpGistScanOpaqueData * SpGistScanOpaque
MemoryContext traversalCxt
void * palloc(Size size)
Definition: mcxt.c:924
int i
#define SPGIST_INNER_CONSISTENT_PROC
Definition: spgist.h:30
IndexScanDesc RelationGetIndexScan(Relation indexRelation, int nkeys, int norderbys)
Definition: genam.c:80
int numberOfOrderBys
Definition: relscan.h:106

◆ spgbuild()

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

Definition at line 75 of file spginsert.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, BufferGetBlockNumber(), BufferGetPage, CurrentMemoryContext, elog, END_CRIT_SECTION, ERROR, IndexBuildResult::heap_tuples, IndexBuildResult::index_tuples, SpGistBuildState::indtuples, initSpGistState(), SpGistState::isBuild, log_newpage_range(), MAIN_FORKNUM, MarkBufferDirty(), MemoryContextDelete(), palloc0(), 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, table_index_build_scan(), SpGistBuildState::tmpCtx, and UnlockReleaseBuffer().

Referenced by spghandler().

76 {
77  IndexBuildResult *result;
78  double reltuples;
79  SpGistBuildState buildstate;
80  Buffer metabuffer,
81  rootbuffer,
82  nullbuffer;
83 
84  if (RelationGetNumberOfBlocks(index) != 0)
85  elog(ERROR, "index \"%s\" already contains data",
87 
88  /*
89  * Initialize the meta page and root pages
90  */
91  metabuffer = SpGistNewBuffer(index);
92  rootbuffer = SpGistNewBuffer(index);
93  nullbuffer = SpGistNewBuffer(index);
94 
98 
100 
101  SpGistInitMetapage(BufferGetPage(metabuffer));
102  MarkBufferDirty(metabuffer);
103  SpGistInitBuffer(rootbuffer, SPGIST_LEAF);
104  MarkBufferDirty(rootbuffer);
106  MarkBufferDirty(nullbuffer);
107 
108 
110 
111  UnlockReleaseBuffer(metabuffer);
112  UnlockReleaseBuffer(rootbuffer);
113  UnlockReleaseBuffer(nullbuffer);
114 
115  /*
116  * Now insert all the heap data into the index
117  */
118  initSpGistState(&buildstate.spgstate, index);
119  buildstate.spgstate.isBuild = true;
120  buildstate.indtuples = 0;
121 
123  "SP-GiST build temporary context",
125 
126  reltuples = table_index_build_scan(heap, index, indexInfo, true, true,
127  spgistBuildCallback, (void *) &buildstate,
128  NULL);
129 
130  MemoryContextDelete(buildstate.tmpCtx);
131 
132  SpGistUpdateMetaPage(index);
133 
134  /*
135  * We didn't write WAL records as we built the index, so if WAL-logging is
136  * required, write all pages to the WAL now.
137  */
138  if (RelationNeedsWAL(index))
139  {
141  0, RelationGetNumberOfBlocks(index),
142  true);
143  }
144 
145  result = (IndexBuildResult *) palloc0(sizeof(IndexBuildResult));
146  result->heap_tuples = reltuples;
147  result->index_tuples = buildstate.indtuples;
148 
149  return result;
150 }
void SpGistUpdateMetaPage(Relation index)
Definition: spgutils.c:276
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
#define AllocSetContextCreate
Definition: memutils.h:169
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1458
#define END_CRIT_SECTION()
Definition: miscadmin.h:134
#define SPGIST_NULLS
#define START_CRIT_SECTION()
Definition: miscadmin.h:132
SpGistState spgstate
Definition: spginsert.c:35
#define SPGIST_ROOT_BLKNO
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3376
#define ERROR
Definition: elog.h:43
static double table_index_build_scan(Relation table_rel, Relation index_rel, struct IndexInfo *index_info, bool allow_sync, bool progress, IndexBuildCallback callback, void *callback_state, TableScanDesc scan)
Definition: tableam.h:1499
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:191
#define SPGIST_NULL_BLKNO
#define SPGIST_METAPAGE_BLKNO
void initSpGistState(SpGistState *state, Relation index)
Definition: spgutils.c:181
#define RelationGetRelationName(relation)
Definition: rel.h:450
static void spgistBuildCallback(Relation index, HeapTuple htup, Datum *values, bool *isnull, bool tupleIsAlive, void *state)
Definition: spginsert.c:43
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
void SpGistInitBuffer(Buffer b, uint16 f)
Definition: spgutils.c:550
#define BufferGetPage(buffer)
Definition: bufmgr.h:159
void * palloc0(Size size)
Definition: mcxt.c:955
#define RelationGetNumberOfBlocks(reln)
Definition: bufmgr.h:198
Buffer SpGistNewBuffer(Relation index)
Definition: spgutils.c:211
#define Assert(condition)
Definition: c.h:732
void SpGistInitMetapage(Page page)
Definition: spgutils.c:560
#define RelationNeedsWAL(relation)
Definition: rel.h:518
void log_newpage_range(Relation rel, ForkNumber forkNum, BlockNumber startblk, BlockNumber endblk, bool page_std)
Definition: xloginsert.c:1042
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2613
#define elog(elevel,...)
Definition: elog.h:226
MemoryContext tmpCtx
Definition: spginsert.c:37
#define SPGIST_LEAF
int Buffer
Definition: buf.h:23
float4 reltuples
Definition: pg_class.h:63
double index_tuples
Definition: genam.h:33
double heap_tuples
Definition: genam.h:32

◆ spgbuildempty()

void spgbuildempty ( Relation  index)

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

157 {
158  Page page;
159 
160  /* Construct metapage. */
161  page = (Page) palloc(BLCKSZ);
162  SpGistInitMetapage(page);
163 
164  /*
165  * Write the page and log it unconditionally. This is important
166  * particularly for indexes created on tablespaces and databases whose
167  * creation happened after the last redo pointer as recovery removes any
168  * of their existing content when the corresponding create records are
169  * replayed.
170  */
173  (char *) page, true);
175  SPGIST_METAPAGE_BLKNO, page, true);
176 
177  /* Likewise for the root page. */
179 
182  (char *) page, true);
184  SPGIST_ROOT_BLKNO, page, true);
185 
186  /* Likewise for the null-tuples root page. */
188 
191  (char *) page, true);
193  SPGIST_NULL_BLKNO, page, true);
194 
195  /*
196  * An immediate sync is required even if we xlog'd the pages, because the
197  * writes did not go through shared buffers and therefore a concurrent
198  * checkpoint may have moved the redo pointer past our xlog record.
199  */
201 }
struct SMgrRelationData * rd_smgr
Definition: rel.h:56
#define SPGIST_NULLS
#define SPGIST_ROOT_BLKNO
RelFileNodeBackend smgr_rnode
Definition: smgr.h:42
#define SPGIST_NULL_BLKNO
void smgrwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync)
Definition: smgr.c:584
#define SPGIST_METAPAGE_BLKNO
RelFileNode node
Definition: relfilenode.h:74
void SpGistInitMetapage(Page page)
Definition: spgutils.c:560
void PageSetChecksumInplace(Page page, BlockNumber blkno)
Definition: bufpage.c:1198
void SpGistInitPage(Page page, uint16 f)
Definition: spgutils.c:535
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:671
Pointer Page
Definition: bufpage.h:78

◆ 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 968 of file spgscan.c.

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

Referenced by spghandler().

969 {
970  SpGistCache *cache;
971 
972  /* We can do it if the opclass config function says so */
973  cache = spgGetCache(index);
974 
975  return cache->config.canReturnData;
976 }
SpGistCache * spgGetCache(Relation index)
Definition: spgutils.c:99
bool canReturnData
Definition: spgist.h:49
spgConfigOut config

◆ spgendscan()

void spgendscan ( IndexScanDesc  scan)

Definition at line 381 of file spgscan.c.

References SpGistState::deadTupleStorage, SpGistScanOpaqueData::infDistances, SpGistScanOpaqueData::keyData, MemoryContextDelete(), IndexScanDescData::numberOfOrderBys, IndexScanDescData::opaque, SpGistScanOpaqueData::orderByTypes, pfree(), SpGistScanOpaqueData::state, SpGistScanOpaqueData::tempCxt, SpGistScanOpaqueData::traversalCxt, IndexScanDescData::xs_orderbynulls, IndexScanDescData::xs_orderbyvals, and SpGistScanOpaqueData::zeroDistances.

Referenced by spghandler().

382 {
384 
387 
388  if (so->keyData)
389  pfree(so->keyData);
390 
391  if (so->state.deadTupleStorage)
393 
394  if (scan->numberOfOrderBys > 0)
395  {
396  pfree(so->orderByTypes);
397  pfree(so->zeroDistances);
398  pfree(so->infDistances);
399  pfree(scan->xs_orderbyvals);
400  pfree(scan->xs_orderbynulls);
401  }
402 
403  pfree(so);
404 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
MemoryContext tempCxt
Datum * xs_orderbyvals
Definition: relscan.h:146
bool * xs_orderbynulls
Definition: relscan.h:147
void pfree(void *pointer)
Definition: mcxt.c:1031
char * deadTupleStorage
SpGistScanOpaqueData * SpGistScanOpaque
MemoryContext traversalCxt
int numberOfOrderBys
Definition: relscan.h:106

◆ spggetbitmap()

int64 spggetbitmap ( IndexScanDesc  scan,
TIDBitmap tbm 
)

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

859 {
861 
862  /* Copy want_itup to *so so we don't need to pass it around separately */
863  so->want_itup = false;
864 
865  so->tbm = tbm;
866  so->ntids = 0;
867 
868  spgWalk(scan->indexRelation, so, true, storeBitmap, scan->xs_snapshot);
869 
870  return so->ntids;
871 }
struct SnapshotData * xs_snapshot
Definition: relscan.h:104
Relation indexRelation
Definition: relscan.h:103
SpGistScanOpaqueData * SpGistScanOpaque
static void spgWalk(Relation index, SpGistScanOpaque so, bool scanWholeIndex, storeRes_func storeRes, Snapshot snapshot)
Definition: spgscan.c:734
static void storeBitmap(SpGistScanOpaque so, ItemPointer heapPtr, Datum leafValue, bool isnull, bool recheck, bool recheckDistances, double *distances)
Definition: spgscan.c:848

◆ spggettuple()

bool spggettuple ( IndexScanDesc  scan,
ScanDirection  dir 
)

Definition at line 910 of file spgscan.c.

References SpGistScanOpaqueData::distances, elog, ERROR, ForwardScanDirection, SpGistScanOpaqueData::heapPtrs, i, index_store_float8_orderby_distances(), IndexScanDescData::indexRelation, SpGistScanOpaqueData::iPtr, SpGistScanOpaqueData::nPtrs, SpGistScanOpaqueData::numberOfOrderBys, IndexScanDescData::opaque, SpGistScanOpaqueData::orderByTypes, pfree(), SpGistScanOpaqueData::recheck, SpGistScanOpaqueData::recheckDistances, SpGistScanOpaqueData::reconTups, spgWalk(), storeGettuple(), SpGistScanOpaqueData::want_itup, IndexScanDescData::xs_heaptid, IndexScanDescData::xs_hitup, IndexScanDescData::xs_recheck, IndexScanDescData::xs_snapshot, and IndexScanDescData::xs_want_itup.

Referenced by spghandler().

911 {
913 
914  if (dir != ForwardScanDirection)
915  elog(ERROR, "SP-GiST only supports forward scan direction");
916 
917  /* Copy want_itup to *so so we don't need to pass it around separately */
918  so->want_itup = scan->xs_want_itup;
919 
920  for (;;)
921  {
922  if (so->iPtr < so->nPtrs)
923  {
924  /* continuing to return reported tuples */
925  scan->xs_heaptid = so->heapPtrs[so->iPtr];
926  scan->xs_recheck = so->recheck[so->iPtr];
927  scan->xs_hitup = so->reconTups[so->iPtr];
928 
929  if (so->numberOfOrderBys > 0)
931  so->distances[so->iPtr],
932  so->recheckDistances[so->iPtr]);
933  so->iPtr++;
934  return true;
935  }
936 
937  if (so->numberOfOrderBys > 0)
938  {
939  /* Must pfree distances to avoid memory leak */
940  int i;
941 
942  for (i = 0; i < so->nPtrs; i++)
943  if (so->distances[i])
944  pfree(so->distances[i]);
945  }
946 
947  if (so->want_itup)
948  {
949  /* Must pfree reconstructed tuples to avoid memory leak */
950  int i;
951 
952  for (i = 0; i < so->nPtrs; i++)
953  pfree(so->reconTups[i]);
954  }
955  so->iPtr = so->nPtrs = 0;
956 
957  spgWalk(scan->indexRelation, so, false, storeGettuple,
958  scan->xs_snapshot);
959 
960  if (so->nPtrs == 0)
961  break; /* must have completed scan */
962  }
963 
964  return false;
965 }
static void storeGettuple(SpGistScanOpaque so, ItemPointer heapPtr, Datum leafValue, bool isnull, bool recheck, bool recheckDistances, double *distances)
Definition: spgscan.c:875
bool recheckDistances[MaxIndexTuplesPerPage]
ItemPointerData heapPtrs[MaxIndexTuplesPerPage]
struct SnapshotData * xs_snapshot
Definition: relscan.h:104
HeapTuple reconTups[MaxIndexTuplesPerPage]
void index_store_float8_orderby_distances(IndexScanDesc scan, Oid *orderByTypes, double *distances, bool recheckOrderBy)
Definition: indexam.c:849
Relation indexRelation
Definition: relscan.h:103
void pfree(void *pointer)
Definition: mcxt.c:1031
#define ERROR
Definition: elog.h:43
ItemPointerData xs_heaptid
Definition: relscan.h:132
double * distances[MaxIndexTuplesPerPage]
bool recheck[MaxIndexTuplesPerPage]
SpGistScanOpaqueData * SpGistScanOpaque
static void spgWalk(Relation index, SpGistScanOpaque so, bool scanWholeIndex, storeRes_func storeRes, Snapshot snapshot)
Definition: spgscan.c:734
HeapTuple xs_hitup
Definition: relscan.h:129
#define elog(elevel,...)
Definition: elog.h:226
int i

◆ spginsert()

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

Definition at line 207 of file spginsert.c.

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

Referenced by spghandler().

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

◆ spgoptions()

bytea* spgoptions ( Datum  reloptions,
bool  validate 
)

Definition at line 587 of file spgutils.c.

References default_reloptions(), and RELOPT_KIND_SPGIST.

Referenced by spghandler().

588 {
589  return default_reloptions(reloptions, validate, RELOPT_KIND_SPGIST);
590 }
bytea * default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
Definition: reloptions.c:1369

◆ spgrescan()

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

Definition at line 335 of file spgscan.c.

References FmgrInfo::fn_oid, get_func_rettype(), i, IndexScanDescData::keyData, memmove, IndexScanDescData::numberOfKeys, IndexScanDescData::numberOfOrderBys, IndexScanDescData::opaque, IndexScanDescData::orderByData, SpGistScanOpaqueData::orderByTypes, resetSpGistScanOpaque(), ScanKeyData::sk_func, and spgPrepareScanKeys().

Referenced by spghandler().

337 {
339 
340  /* copy scankeys into local storage */
341  if (scankey && scan->numberOfKeys > 0)
342  memmove(scan->keyData, scankey,
343  scan->numberOfKeys * sizeof(ScanKeyData));
344 
345  /* initialize order-by data if needed */
346  if (orderbys && scan->numberOfOrderBys > 0)
347  {
348  int i;
349 
350  memmove(scan->orderByData, orderbys,
351  scan->numberOfOrderBys * sizeof(ScanKeyData));
352 
353  for (i = 0; i < scan->numberOfOrderBys; i++)
354  {
355  ScanKey skey = &scan->orderByData[i];
356 
357  /*
358  * Look up the datatype returned by the original ordering
359  * operator. SP-GiST always uses a float8 for the distance
360  * function, but the ordering operator could be anything else.
361  *
362  * XXX: The distance function is only allowed to be lossy if the
363  * ordering operator's result type is float4 or float8. Otherwise
364  * we don't know how to return the distance to the executor. But
365  * we cannot check that here, as we won't know if the distance
366  * function is lossy until it returns *recheck = true for the
367  * first time.
368  */
370  }
371  }
372 
373  /* preprocess scankeys, set up the representation in *so */
374  spgPrepareScanKeys(scan);
375 
376  /* set up starting queue entries */
378 }
struct ScanKeyData * orderByData
Definition: relscan.h:108
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1457
#define memmove(d, s, c)
Definition: c.h:1238
static void spgPrepareScanKeys(IndexScanDesc scan)
Definition: spgscan.c:199
FmgrInfo sk_func
Definition: skey.h:71
SpGistScanOpaqueData * SpGistScanOpaque
Oid fn_oid
Definition: fmgr.h:59
static void resetSpGistScanOpaque(SpGistScanOpaque so)
Definition: spgscan.c:145
struct ScanKeyData * keyData
Definition: relscan.h:107
int i
int numberOfOrderBys
Definition: relscan.h:106

◆ 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:51
void * callback_state
Definition: spgvacuum.c:47
IndexBulkDeleteResult * stats
Definition: spgvacuum.c:45
double num_index_tuples
Definition: genam.h:77
bool estimated_count
Definition: genam.h:49

◆ 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, get_op_rettype(), GETSTRUCT, HeapTupleIsValid, i, identify_opfamily_groups(), INFO, InvalidOid, spgConfigOut::leafType, OpFamilyOpFuncGroup::lefttype, lfirst, catclist::members, catclist::n_members, NameStr, ObjectIdGetDatum, OidFunctionCall2, OidIsValid, OpFamilyOpFuncGroup::operatorset, opfamily_can_sort_type(), 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 function %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  Oid op_rettype;
191 
192  /* TODO: Check that only allowed strategy numbers exist */
193  if (oprform->amopstrategy < 1 || oprform->amopstrategy > 63)
194  {
195  ereport(INFO,
196  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
197  errmsg("operator family \"%s\" of access method %s contains operator %s with invalid strategy number %d",
198  opfamilyname, "spgist",
199  format_operator(oprform->amopopr),
200  oprform->amopstrategy)));
201  result = false;
202  }
203 
204  /* spgist supports ORDER BY operators */
205  if (oprform->amoppurpose != AMOP_SEARCH)
206  {
207  /* ... and operator result must match the claimed btree opfamily */
208  op_rettype = get_op_rettype(oprform->amopopr);
209  if (!opfamily_can_sort_type(oprform->amopsortfamily, op_rettype))
210  {
211  ereport(INFO,
212  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
213  errmsg("operator family \"%s\" of access method %s contains invalid ORDER BY specification for operator %s",
214  opfamilyname, "spgist",
215  format_operator(oprform->amopopr))));
216  result = false;
217  }
218  }
219  else
220  op_rettype = BOOLOID;
221 
222  /* Check operator signature --- same for all spgist strategies */
223  if (!check_amop_signature(oprform->amopopr, op_rettype,
224  oprform->amoplefttype,
225  oprform->amoprighttype))
226  {
227  ereport(INFO,
228  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
229  errmsg("operator family \"%s\" of access method %s contains operator %s with wrong signature",
230  opfamilyname, "spgist",
231  format_operator(oprform->amopopr))));
232  result = false;
233  }
234  }
235 
236  /* Now check for inconsistent groups of operators/functions */
237  opclassgroup = NULL;
238  foreach(lc, grouplist)
239  {
240  OpFamilyOpFuncGroup *thisgroup = (OpFamilyOpFuncGroup *) lfirst(lc);
241 
242  /* Remember the group exactly matching the test opclass */
243  if (thisgroup->lefttype == opcintype &&
244  thisgroup->righttype == opcintype)
245  opclassgroup = thisgroup;
246 
247  /*
248  * Complain if there are any datatype pairs with functions but no
249  * operators. This is about the best we can do for now to detect
250  * missing operators.
251  */
252  if (thisgroup->operatorset == 0)
253  {
254  ereport(INFO,
255  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
256  errmsg("operator family \"%s\" of access method %s is missing operator(s) for types %s and %s",
257  opfamilyname, "spgist",
258  format_type_be(thisgroup->lefttype),
259  format_type_be(thisgroup->righttype))));
260  result = false;
261  }
262 
263  /*
264  * Complain if we're missing functions for any datatype, remembering
265  * that SP-GiST doesn't use cross-type support functions.
266  */
267  if (thisgroup->lefttype != thisgroup->righttype)
268  continue;
269 
270  for (i = 1; i <= SPGISTNProc; i++)
271  {
272  if ((thisgroup->functionset & (((uint64) 1) << i)) != 0)
273  continue; /* got it */
274  ereport(INFO,
275  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
276  errmsg("operator family \"%s\" of access method %s is missing support function %d for type %s",
277  opfamilyname, "spgist", i,
278  format_type_be(thisgroup->lefttype))));
279  result = false;
280  }
281  }
282 
283  /* Check that the originally-named opclass is supported */
284  /* (if group is there, we already checked it adequately above) */
285  if (!opclassgroup)
286  {
287  ereport(INFO,
288  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
289  errmsg("operator class \"%s\" of access method %s is missing operator(s)",
290  opclassname, "spgist")));
291  result = false;
292  }
293 
294  ReleaseCatCacheList(proclist);
295  ReleaseCatCacheList(oprlist);
296  ReleaseSysCache(familytup);
297  ReleaseSysCache(classtup);
298 
299  return result;
300 }
int n_members
Definition: catcache.h:176
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define SPGIST_LEAF_CONSISTENT_PROC
Definition: spgist.h:31
bool opfamily_can_sort_type(Oid opfamilyoid, Oid datatypeoid)
Definition: amvalidate.c:217
#define PointerGetDatum(X)
Definition: postgres.h:556
FormData_pg_amproc * Form_pg_amproc
Definition: pg_amproc.h:68
int errcode(int sqlerrcode)
Definition: elog.c:570
#define INFO
Definition: elog.h:33
char * format_type_be(Oid type_oid)
Definition: format_type.c:326
char * format_operator(Oid operator_oid)
Definition: regproc.c:820
Oid attType
Definition: spgist.h:41
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:638
Oid get_op_rettype(Oid opno)
Definition: lsyscache.c:1140
void ReleaseCatCacheList(CatCList *list)
Definition: catcache.c:1782
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:507
#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:210
#define ereport(elevel, rest)
Definition: elog.h:141
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
FormData_pg_opfamily * Form_pg_opfamily
Definition: pg_opfamily.h:51
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
#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:190
#define SPGIST_COMPRESS_PROC
Definition: spgist.h:32
#define SPGIST_CONFIG_PROC
Definition: spgist.h:27
bool check_amop_signature(Oid opno, Oid restype, Oid lefttype, Oid righttype)
Definition: amvalidate.c:194
#define OidFunctionCall2(functionId, arg1, arg2)
Definition: fmgr.h:656
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define SPGISTNProc
Definition: spgist.h:34
FormData_pg_amop * Form_pg_amop
Definition: pg_amop.h:88
#define elog(elevel,...)
Definition: elog.h:226
int i
#define NameStr(name)
Definition: c.h:609
Oid leafType
Definition: spgist.h:48
#define SPGIST_INNER_CONSISTENT_PROC
Definition: spgist.h:30
HeapTupleData tuple
Definition: catcache.h:121
#define SPGIST_CHOOSE_PROC
Definition: spgist.h:28
FormData_pg_opclass * Form_pg_opclass
Definition: pg_opclass.h:83
#define SPGIST_PICKSPLIT_PROC
Definition: spgist.h:29
Definition: pg_list.h:50