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_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 24 of file spgist.h.

Referenced by spgdoinsert(), and spgvalidate().

◆ SPGIST_COMPRESS_PROC

#define SPGIST_COMPRESS_PROC   6

Definition at line 28 of file spgist.h.

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

◆ SPGIST_CONFIG_PROC

#define SPGIST_CONFIG_PROC   1

Definition at line 23 of file spgist.h.

Referenced by spgGetCache(), and spgvalidate().

◆ SPGIST_INNER_CONSISTENT_PROC

#define SPGIST_INNER_CONSISTENT_PROC   4

Definition at line 26 of file spgist.h.

Referenced by spgbeginscan(), and spgvalidate().

◆ SPGIST_LEAF_CONSISTENT_PROC

#define SPGIST_LEAF_CONSISTENT_PROC   5

Definition at line 27 of file spgist.h.

Referenced by spgbeginscan(), and spgvalidate().

◆ SPGIST_PICKSPLIT_PROC

#define SPGIST_PICKSPLIT_PROC   3

Definition at line 25 of file spgist.h.

Referenced by doPickSplit(), and spgvalidate().

◆ SPGISTNProc

#define SPGISTNProc   6

Definition at line 30 of file spgist.h.

Referenced by spghandler(), and spgvalidate().

◆ SPGISTNRequiredProc

#define SPGISTNRequiredProc   5

Definition at line 29 of file spgist.h.

Typedef Documentation

◆ spgChooseIn

typedef struct spgChooseIn spgChooseIn

◆ spgChooseOut

typedef struct spgChooseOut spgChooseOut

◆ spgChooseResultType

◆ spgConfigIn

typedef struct spgConfigIn spgConfigIn

◆ spgConfigOut

typedef struct spgConfigOut spgConfigOut

◆ spgInnerConsistentIn

◆ spgInnerConsistentOut

◆ spgLeafConsistentIn

◆ spgLeafConsistentOut

◆ spgPickSplitIn

◆ spgPickSplitOut

Enumeration Type Documentation

◆ spgChooseResultType

Enumerator
spgMatchNode 
spgAddNode 
spgSplitTuple 

Definition at line 66 of file spgist.h.

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

Function Documentation

◆ spgbeginscan()

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

Definition at line 295 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, SpGistScanOpaqueData::nonNullOrderByOffsets, 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().

296 {
297  IndexScanDesc scan;
298  SpGistScanOpaque so;
299  int i;
300 
301  scan = RelationGetIndexScan(rel, keysz, orderbysz);
302 
304  if (keysz > 0)
305  so->keyData = (ScanKey) palloc(sizeof(ScanKeyData) * keysz);
306  else
307  so->keyData = NULL;
308  initSpGistState(&so->state, scan->indexRelation);
309 
311  "SP-GiST search temporary context",
314  "SP-GiST traversal-value context",
316 
317  /* Set up indexTupDesc and xs_hitupdesc in case it's an index-only scan */
318  so->indexTupDesc = scan->xs_hitupdesc = RelationGetDescr(rel);
319 
320  /* Allocate various arrays needed for order-by scans */
321  if (scan->numberOfOrderBys > 0)
322  {
323  /* This will be filled in spgrescan, but allocate the space here */
324  so->orderByTypes = (Oid *)
325  palloc(sizeof(Oid) * scan->numberOfOrderBys);
326  so->nonNullOrderByOffsets = (int *)
327  palloc(sizeof(int) * scan->numberOfOrderBys);
328 
329  /* These arrays have constant contents, so we can fill them now */
330  so->zeroDistances = (double *)
331  palloc(sizeof(double) * scan->numberOfOrderBys);
332  so->infDistances = (double *)
333  palloc(sizeof(double) * scan->numberOfOrderBys);
334 
335  for (i = 0; i < scan->numberOfOrderBys; i++)
336  {
337  so->zeroDistances[i] = 0.0;
339  }
340 
341  scan->xs_orderbyvals = (Datum *)
342  palloc0(sizeof(Datum) * scan->numberOfOrderBys);
343  scan->xs_orderbynulls = (bool *)
344  palloc(sizeof(bool) * scan->numberOfOrderBys);
345  memset(scan->xs_orderbynulls, true,
346  sizeof(bool) * scan->numberOfOrderBys);
347  }
348 
352 
356 
357  so->indexCollation = rel->rd_indcollation[0];
358 
359  scan->opaque = so;
360 
361  return scan;
362 }
#define AllocSetContextCreate
Definition: memutils.h:170
static float8 get_float8_infinity(void)
Definition: float.h:90
#define SPGIST_LEAF_CONSISTENT_PROC
Definition: spgist.h:27
FmgrInfo * index_getprocinfo(Relation irel, AttrNumber attnum, uint16 procnum)
Definition: indexam.c:794
#define RelationGetDescr(relation)
Definition: rel.h:448
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:192
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:980
uintptr_t Datum
Definition: postgres.h:367
SpGistScanOpaqueData * SpGistScanOpaque
MemoryContext traversalCxt
void * palloc(Size size)
Definition: mcxt.c:949
int i
#define SPGIST_INNER_CONSISTENT_PROC
Definition: spgist.h:26
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 }
static void spgistBuildCallback(Relation index, ItemPointer tid, Datum *values, bool *isnull, bool tupleIsAlive, void *state)
Definition: spginsert.c:43
void SpGistUpdateMetaPage(Relation index)
Definition: spgutils.c:276
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
#define AllocSetContextCreate
Definition: memutils.h:170
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:3388
#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:192
#define SPGIST_NULL_BLKNO
#define SPGIST_METAPAGE_BLKNO
void initSpGistState(SpGistState *state, Relation index)
Definition: spgutils.c:181
#define RelationGetRelationName(relation)
Definition: rel.h:456
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
void SpGistInitBuffer(Buffer b, uint16 f)
Definition: spgutils.c:549
#define BufferGetPage(buffer)
Definition: bufmgr.h:159
void * palloc0(Size size)
Definition: mcxt.c:980
#define RelationGetNumberOfBlocks(reln)
Definition: bufmgr.h:198
Buffer SpGistNewBuffer(Relation index)
Definition: spgutils.c:211
#define Assert(condition)
Definition: c.h:739
void SpGistInitMetapage(Page page)
Definition: spgutils.c:559
#define RelationNeedsWAL(relation)
Definition: rel.h:524
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:228
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:530
#define SPGIST_METAPAGE_BLKNO
RelFileNode node
Definition: relfilenode.h:74
void SpGistInitMetapage(Page page)
Definition: spgutils.c:559
void PageSetChecksumInplace(Page page, BlockNumber blkno)
Definition: bufpage.c:1198
void SpGistInitPage(Page page, uint16 f)
Definition: spgutils.c:534
void * palloc(Size size)
Definition: mcxt.c:949
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:637
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:980
void * callback_state
Definition: spgvacuum.c:47
IndexBulkDeleteResult * stats
Definition: spgvacuum.c:45

◆ spgcanreturn()

bool spgcanreturn ( Relation  index,
int  attno 
)

Definition at line 1019 of file spgscan.c.

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

Referenced by spghandler().

1020 {
1021  SpGistCache *cache;
1022 
1023  /* We can do it if the opclass config function says so */
1024  cache = spgGetCache(index);
1025 
1026  return cache->config.canReturnData;
1027 }
SpGistCache * spgGetCache(Relation index)
Definition: spgutils.c:99
bool canReturnData
Definition: spgist.h:45
spgConfigOut config

◆ spgendscan()

void spgendscan ( IndexScanDesc  scan)

Definition at line 411 of file spgscan.c.

References SpGistState::deadTupleStorage, SpGistScanOpaqueData::infDistances, SpGistScanOpaqueData::keyData, MemoryContextDelete(), SpGistScanOpaqueData::nonNullOrderByOffsets, 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().

412 {
414 
417 
418  if (so->keyData)
419  pfree(so->keyData);
420 
421  if (so->state.deadTupleStorage)
423 
424  if (scan->numberOfOrderBys > 0)
425  {
426  pfree(so->orderByTypes);
428  pfree(so->zeroDistances);
429  pfree(so->infDistances);
430  pfree(scan->xs_orderbyvals);
431  pfree(scan->xs_orderbynulls);
432  }
433 
434  pfree(so);
435 }
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:1056
char * deadTupleStorage
SpGistScanOpaqueData * SpGistScanOpaque
MemoryContext traversalCxt
int numberOfOrderBys
Definition: relscan.h:106

◆ spggetbitmap()

int64 spggetbitmap ( IndexScanDesc  scan,
TIDBitmap tbm 
)

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

890 {
892 
893  /* Copy want_itup to *so so we don't need to pass it around separately */
894  so->want_itup = false;
895 
896  so->tbm = tbm;
897  so->ntids = 0;
898 
899  spgWalk(scan->indexRelation, so, true, storeBitmap, scan->xs_snapshot);
900 
901  return so->ntids;
902 }
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:765
static void storeBitmap(SpGistScanOpaque so, ItemPointer heapPtr, Datum leafValue, bool isnull, bool recheck, bool recheckDistances, double *distances)
Definition: spgscan.c:879

◆ spggettuple()

bool spggettuple ( IndexScanDesc  scan,
ScanDirection  dir 
)

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

962 {
964 
965  if (dir != ForwardScanDirection)
966  elog(ERROR, "SP-GiST only supports forward scan direction");
967 
968  /* Copy want_itup to *so so we don't need to pass it around separately */
969  so->want_itup = scan->xs_want_itup;
970 
971  for (;;)
972  {
973  if (so->iPtr < so->nPtrs)
974  {
975  /* continuing to return reported tuples */
976  scan->xs_heaptid = so->heapPtrs[so->iPtr];
977  scan->xs_recheck = so->recheck[so->iPtr];
978  scan->xs_hitup = so->reconTups[so->iPtr];
979 
980  if (so->numberOfOrderBys > 0)
982  so->distances[so->iPtr],
983  so->recheckDistances[so->iPtr]);
984  so->iPtr++;
985  return true;
986  }
987 
988  if (so->numberOfOrderBys > 0)
989  {
990  /* Must pfree distances to avoid memory leak */
991  int i;
992 
993  for (i = 0; i < so->nPtrs; i++)
994  if (so->distances[i])
995  pfree(so->distances[i]);
996  }
997 
998  if (so->want_itup)
999  {
1000  /* Must pfree reconstructed tuples to avoid memory leak */
1001  int i;
1002 
1003  for (i = 0; i < so->nPtrs; i++)
1004  pfree(so->reconTups[i]);
1005  }
1006  so->iPtr = so->nPtrs = 0;
1007 
1008  spgWalk(scan->indexRelation, so, false, storeGettuple,
1009  scan->xs_snapshot);
1010 
1011  if (so->nPtrs == 0)
1012  break; /* must have completed scan */
1013  }
1014 
1015  return false;
1016 }
IndexOrderByDistance * distances[MaxIndexTuplesPerPage]
bool recheckDistances[MaxIndexTuplesPerPage]
ItemPointerData heapPtrs[MaxIndexTuplesPerPage]
struct SnapshotData * xs_snapshot
Definition: relscan.h:104
HeapTuple reconTups[MaxIndexTuplesPerPage]
Relation indexRelation
Definition: relscan.h:103
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
ItemPointerData xs_heaptid
Definition: relscan.h:132
bool recheck[MaxIndexTuplesPerPage]
void index_store_float8_orderby_distances(IndexScanDesc scan, Oid *orderByTypes, IndexOrderByDistance *distances, bool recheckOrderBy)
Definition: indexam.c:849
SpGistScanOpaqueData * SpGistScanOpaque
static void storeGettuple(SpGistScanOpaque so, ItemPointer heapPtr, Datum leafValue, bool isnull, bool recheck, bool recheckDistances, double *nonNullDistances)
Definition: spgscan.c:906
static void spgWalk(Relation index, SpGistScanOpaque so, bool scanWholeIndex, storeRes_func storeRes, Snapshot snapshot)
Definition: spgscan.c:765
HeapTuple xs_hitup
Definition: relscan.h:129
#define elog(elevel,...)
Definition: elog.h:228
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:170
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:136
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
void initSpGistState(SpGistState *state, Relation index)
Definition: spgutils.c: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 586 of file spgutils.c.

References build_reloptions(), fillfactor, lengthof, offsetof, RELOPT_KIND_SPGIST, and RELOPT_TYPE_INT.

Referenced by spghandler().

587 {
588  static const relopt_parse_elt tab[] = {
590  };
591 
592  return (bytea *) build_reloptions(reloptions, validate,
594  sizeof(SpGistOptions),
595  tab, lengthof(tab));
596 
597 }
#define lengthof(array)
Definition: c.h:669
void * build_reloptions(Datum reloptions, bool validate, relopt_kind kind, Size relopt_struct_size, const relopt_parse_elt *relopt_elems, int num_relopt_elems)
Definition: reloptions.c:1552
int fillfactor
Definition: pgbench.c:160
Definition: c.h:556
#define offsetof(type, field)
Definition: c.h:662

◆ spgrescan()

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

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

367 {
369 
370  /* copy scankeys into local storage */
371  if (scankey && scan->numberOfKeys > 0)
372  memmove(scan->keyData, scankey,
373  scan->numberOfKeys * sizeof(ScanKeyData));
374 
375  /* initialize order-by data if needed */
376  if (orderbys && scan->numberOfOrderBys > 0)
377  {
378  int i;
379 
380  memmove(scan->orderByData, orderbys,
381  scan->numberOfOrderBys * sizeof(ScanKeyData));
382 
383  for (i = 0; i < scan->numberOfOrderBys; i++)
384  {
385  ScanKey skey = &scan->orderByData[i];
386 
387  /*
388  * Look up the datatype returned by the original ordering
389  * operator. SP-GiST always uses a float8 for the distance
390  * function, but the ordering operator could be anything else.
391  *
392  * XXX: The distance function is only allowed to be lossy if the
393  * ordering operator's result type is float4 or float8. Otherwise
394  * we don't know how to return the distance to the executor. But
395  * we cannot check that here, as we won't know if the distance
396  * function is lossy until it returns *recheck = true for the
397  * first time.
398  */
400  }
401  }
402 
403  /* preprocess scankeys, set up the representation in *so */
404  spgPrepareScanKeys(scan);
405 
406  /* set up starting queue entries */
408 }
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:1267
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:980
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:27
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:608
#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:37
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:645
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:1116
FormData_pg_opfamily * Form_pg_opfamily
Definition: pg_opfamily.h:51
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#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:28
#define SPGIST_CONFIG_PROC
Definition: spgist.h:23
bool check_amop_signature(Oid opno, Oid restype, Oid lefttype, Oid righttype)
Definition: amvalidate.c:194
#define OidFunctionCall2(functionId, arg1, arg2)
Definition: fmgr.h:655
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define SPGISTNProc
Definition: spgist.h:30
FormData_pg_amop * Form_pg_amop
Definition: pg_amop.h:88
#define elog(elevel,...)
Definition: elog.h:228
int i
#define NameStr(name)
Definition: c.h:616
Oid leafType
Definition: spgist.h:44
#define SPGIST_INNER_CONSISTENT_PROC
Definition: spgist.h:26
HeapTupleData tuple
Definition: catcache.h:121
#define SPGIST_CHOOSE_PROC
Definition: spgist.h:24
FormData_pg_opclass * Form_pg_opclass
Definition: pg_opclass.h:83
#define SPGIST_PICKSPLIT_PROC
Definition: spgist.h:25
Definition: pg_list.h:50