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 SPGIST_OPTIONS_PROC   7
 
#define SPGISTNRequiredProc   5
 
#define SPGISTNProc   7
 

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, bool indexUnchanged, 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)
 
void spgadjustmembers (Oid opfamilyoid, Oid opclassoid, List *operators, List *functions)
 

Macro Definition Documentation

◆ SPGIST_CHOOSE_PROC

#define SPGIST_CHOOSE_PROC   2

Definition at line 24 of file spgist.h.

◆ SPGIST_COMPRESS_PROC

#define SPGIST_COMPRESS_PROC   6

Definition at line 28 of file spgist.h.

◆ SPGIST_CONFIG_PROC

#define SPGIST_CONFIG_PROC   1

Definition at line 23 of file spgist.h.

◆ SPGIST_INNER_CONSISTENT_PROC

#define SPGIST_INNER_CONSISTENT_PROC   4

Definition at line 26 of file spgist.h.

◆ SPGIST_LEAF_CONSISTENT_PROC

#define SPGIST_LEAF_CONSISTENT_PROC   5

Definition at line 27 of file spgist.h.

◆ SPGIST_OPTIONS_PROC

#define SPGIST_OPTIONS_PROC   7

Definition at line 29 of file spgist.h.

◆ SPGIST_PICKSPLIT_PROC

#define SPGIST_PICKSPLIT_PROC   3

Definition at line 25 of file spgist.h.

◆ SPGISTNProc

#define SPGISTNProc   7

Definition at line 31 of file spgist.h.

◆ SPGISTNRequiredProc

#define SPGISTNRequiredProc   5

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

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

Function Documentation

◆ spgadjustmembers()

void spgadjustmembers ( Oid  opfamilyoid,
Oid  opclassoid,
List operators,
List functions 
)

Definition at line 332 of file spgvalidate.c.

336 {
337  ListCell *lc;
338 
339  /*
340  * Operator members of an SP-GiST opfamily should never have hard
341  * dependencies, since their connection to the opfamily depends only on
342  * what the support functions think, and that can be altered. For
343  * consistency, we make all soft dependencies point to the opfamily,
344  * though a soft dependency on the opclass would work as well in the
345  * CREATE OPERATOR CLASS case.
346  */
347  foreach(lc, operators)
348  {
349  OpFamilyMember *op = (OpFamilyMember *) lfirst(lc);
350 
351  op->ref_is_hard = false;
352  op->ref_is_family = true;
353  op->refobjid = opfamilyoid;
354  }
355 
356  /*
357  * Required support functions should have hard dependencies. Preferably
358  * those are just dependencies on the opclass, but if we're in ALTER
359  * OPERATOR FAMILY, we leave the dependency pointing at the whole
360  * opfamily. (Given that SP-GiST opclasses generally don't share
361  * opfamilies, it seems unlikely to be worth working harder.)
362  */
363  foreach(lc, functions)
364  {
365  OpFamilyMember *op = (OpFamilyMember *) lfirst(lc);
366 
367  switch (op->number)
368  {
369  case SPGIST_CONFIG_PROC:
370  case SPGIST_CHOOSE_PROC:
374  /* Required support function */
375  op->ref_is_hard = true;
376  break;
378  case SPGIST_OPTIONS_PROC:
379  /* Optional, so force it to be a soft family dependency */
380  op->ref_is_hard = false;
381  op->ref_is_family = true;
382  op->refobjid = opfamilyoid;
383  break;
384  default:
385  ereport(ERROR,
386  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
387  errmsg("support function number %d is invalid for access method %s",
388  op->number, "spgist")));
389  break;
390  }
391  }
392 }
int errcode(int sqlerrcode)
Definition: elog.c:859
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
#define lfirst(lc)
Definition: pg_list.h:172
static const struct fns functions
Definition: regcomp.c:356
#define SPGIST_OPTIONS_PROC
Definition: spgist.h:29
#define SPGIST_COMPRESS_PROC
Definition: spgist.h:28
#define SPGIST_CHOOSE_PROC
Definition: spgist.h:24
#define SPGIST_LEAF_CONSISTENT_PROC
Definition: spgist.h:27
#define SPGIST_CONFIG_PROC
Definition: spgist.h:23
#define SPGIST_PICKSPLIT_PROC
Definition: spgist.h:25
#define SPGIST_INNER_CONSISTENT_PROC
Definition: spgist.h:26
Oid refobjid
Definition: amapi.h:90
bool ref_is_family
Definition: amapi.h:89
int number
Definition: amapi.h:84
bool ref_is_hard
Definition: amapi.h:88

References ereport, errcode(), errmsg(), ERROR, functions, lfirst, OpFamilyMember::number, OpFamilyMember::ref_is_family, OpFamilyMember::ref_is_hard, OpFamilyMember::refobjid, SPGIST_CHOOSE_PROC, SPGIST_COMPRESS_PROC, SPGIST_CONFIG_PROC, SPGIST_INNER_CONSISTENT_PROC, SPGIST_LEAF_CONSISTENT_PROC, SPGIST_OPTIONS_PROC, and SPGIST_PICKSPLIT_PROC.

Referenced by spghandler().

◆ spgbeginscan()

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

Definition at line 304 of file spgscan.c.

305 {
306  IndexScanDesc scan;
307  SpGistScanOpaque so;
308  int i;
309 
310  scan = RelationGetIndexScan(rel, keysz, orderbysz);
311 
313  if (keysz > 0)
314  so->keyData = (ScanKey) palloc(sizeof(ScanKeyData) * keysz);
315  else
316  so->keyData = NULL;
317  initSpGistState(&so->state, scan->indexRelation);
318 
320  "SP-GiST search temporary context",
323  "SP-GiST traversal-value context",
325 
326  /*
327  * Set up reconTupDesc and xs_hitupdesc in case it's an index-only scan,
328  * making sure that the key column is shown as being of type attType.
329  * (It's rather annoying to do this work when it might be wasted, but for
330  * most opclasses we can re-use the index reldesc instead of making one.)
331  */
332  so->reconTupDesc = scan->xs_hitupdesc =
333  getSpGistTupleDesc(rel, &so->state.attType);
334 
335  /* Allocate various arrays needed for order-by scans */
336  if (scan->numberOfOrderBys > 0)
337  {
338  /* This will be filled in spgrescan, but allocate the space here */
339  so->orderByTypes = (Oid *)
340  palloc(sizeof(Oid) * scan->numberOfOrderBys);
341  so->nonNullOrderByOffsets = (int *)
342  palloc(sizeof(int) * scan->numberOfOrderBys);
343 
344  /* These arrays have constant contents, so we can fill them now */
345  so->zeroDistances = (double *)
346  palloc(sizeof(double) * scan->numberOfOrderBys);
347  so->infDistances = (double *)
348  palloc(sizeof(double) * scan->numberOfOrderBys);
349 
350  for (i = 0; i < scan->numberOfOrderBys; i++)
351  {
352  so->zeroDistances[i] = 0.0;
354  }
355 
356  scan->xs_orderbyvals = (Datum *)
357  palloc0(sizeof(Datum) * scan->numberOfOrderBys);
358  scan->xs_orderbynulls = (bool *)
359  palloc(sizeof(bool) * scan->numberOfOrderBys);
360  memset(scan->xs_orderbynulls, true,
361  sizeof(bool) * scan->numberOfOrderBys);
362  }
363 
367 
371 
372  so->indexCollation = rel->rd_indcollation[0];
373 
374  scan->opaque = so;
375 
376  return scan;
377 }
static float8 get_float8_infinity(void)
Definition: float.h:94
void fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo, MemoryContext destcxt)
Definition: fmgr.c:580
IndexScanDesc RelationGetIndexScan(Relation indexRelation, int nkeys, int norderbys)
Definition: genam.c:78
FmgrInfo * index_getprocinfo(Relation irel, AttrNumber attnum, uint16 procnum)
Definition: indexam.c:861
int i
Definition: isn.c:73
void * palloc0(Size size)
Definition: mcxt.c:1346
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
void * palloc(Size size)
Definition: mcxt.c:1316
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
uintptr_t Datum
Definition: postgres.h:64
unsigned int Oid
Definition: postgres_ext.h:31
ScanKeyData * ScanKey
Definition: skey.h:75
SpGistScanOpaqueData * SpGistScanOpaque
void initSpGistState(SpGistState *state, Relation index)
Definition: spgutils.c:340
TupleDesc getSpGistTupleDesc(Relation index, SpGistTypeDesc *keyType)
Definition: spgutils.c:309
bool * xs_orderbynulls
Definition: relscan.h:162
int numberOfOrderBys
Definition: relscan.h:121
struct TupleDescData * xs_hitupdesc
Definition: relscan.h:145
Relation indexRelation
Definition: relscan.h:118
Datum * xs_orderbyvals
Definition: relscan.h:161
Oid * rd_indcollation
Definition: rel.h:217
MemoryContext traversalCxt
MemoryContext tempCxt
SpGistTypeDesc attType

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, SpGistState::attType, CurrentMemoryContext, fmgr_info_copy(), get_float8_infinity(), getSpGistTupleDesc(), i, index_getprocinfo(), SpGistScanOpaqueData::indexCollation, IndexScanDescData::indexRelation, SpGistScanOpaqueData::infDistances, initSpGistState(), SpGistScanOpaqueData::innerConsistentFn, SpGistScanOpaqueData::keyData, SpGistScanOpaqueData::leafConsistentFn, SpGistScanOpaqueData::nonNullOrderByOffsets, IndexScanDescData::numberOfOrderBys, IndexScanDescData::opaque, SpGistScanOpaqueData::orderByTypes, palloc(), palloc0(), RelationData::rd_indcollation, SpGistScanOpaqueData::reconTupDesc, 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().

◆ spgbuild()

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

Definition at line 73 of file spginsert.c.

74 {
75  IndexBuildResult *result;
76  double reltuples;
77  SpGistBuildState buildstate;
78  Buffer metabuffer,
79  rootbuffer,
80  nullbuffer;
81 
83  elog(ERROR, "index \"%s\" already contains data",
85 
86  /*
87  * Initialize the meta page and root pages
88  */
89  metabuffer = SpGistNewBuffer(index);
90  rootbuffer = SpGistNewBuffer(index);
91  nullbuffer = SpGistNewBuffer(index);
92 
96 
98 
99  SpGistInitMetapage(BufferGetPage(metabuffer));
100  MarkBufferDirty(metabuffer);
101  SpGistInitBuffer(rootbuffer, SPGIST_LEAF);
102  MarkBufferDirty(rootbuffer);
104  MarkBufferDirty(nullbuffer);
105 
106 
108 
109  UnlockReleaseBuffer(metabuffer);
110  UnlockReleaseBuffer(rootbuffer);
111  UnlockReleaseBuffer(nullbuffer);
112 
113  /*
114  * Now insert all the heap data into the index
115  */
116  initSpGistState(&buildstate.spgstate, index);
117  buildstate.spgstate.isBuild = true;
118  buildstate.indtuples = 0;
119 
121  "SP-GiST build temporary context",
123 
124  reltuples = table_index_build_scan(heap, index, indexInfo, true, true,
125  spgistBuildCallback, (void *) &buildstate,
126  NULL);
127 
128  MemoryContextDelete(buildstate.tmpCtx);
129 
131 
132  /*
133  * We didn't write WAL records as we built the index, so if WAL-logging is
134  * required, write all pages to the WAL now.
135  */
136  if (RelationNeedsWAL(index))
137  {
140  true);
141  }
142 
143  result = (IndexBuildResult *) palloc0(sizeof(IndexBuildResult));
144  result->heap_tuples = reltuples;
145  result->index_tuples = buildstate.indtuples;
146 
147  return result;
148 }
int Buffer
Definition: buf.h:23
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:3667
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:4867
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:2474
#define RelationGetNumberOfBlocks(reln)
Definition: bufmgr.h:281
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:408
#define Assert(condition)
Definition: c.h:858
#define elog(elevel,...)
Definition: elog.h:224
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:454
#define START_CRIT_SECTION()
Definition: miscadmin.h:149
#define END_CRIT_SECTION()
Definition: miscadmin.h:151
#define RelationGetRelationName(relation)
Definition: rel.h:539
#define RelationNeedsWAL(relation)
Definition: rel.h:628
@ MAIN_FORKNUM
Definition: relpath.h:50
static void spgistBuildCallback(Relation index, ItemPointer tid, Datum *values, bool *isnull, bool tupleIsAlive, void *state)
Definition: spginsert.c:41
#define SPGIST_NULL_BLKNO
#define SPGIST_METAPAGE_BLKNO
#define SPGIST_NULLS
#define SPGIST_LEAF
#define SPGIST_ROOT_BLKNO
void SpGistUpdateMetaPage(Relation index)
Definition: spgutils.c:431
Buffer SpGistNewBuffer(Relation index)
Definition: spgutils.c:375
void SpGistInitBuffer(Buffer b, uint16 f)
Definition: spgutils.c:703
void SpGistInitMetapage(Page page)
Definition: spgutils.c:713
double heap_tuples
Definition: genam.h:32
double index_tuples
Definition: genam.h:33
MemoryContext tmpCtx
Definition: spginsert.c:35
SpGistState spgstate
Definition: spginsert.c:33
Definition: type.h:95
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:1713
void log_newpage_range(Relation rel, ForkNumber forknum, BlockNumber startblk, BlockNumber endblk, bool page_std)
Definition: xloginsert.c:1270

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, 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().

◆ spgbuildempty()

void spgbuildempty ( Relation  index)

Definition at line 154 of file spginsert.c.

155 {
156  BulkWriteState *bulkstate;
158 
159  bulkstate = smgr_bulk_start_rel(index, INIT_FORKNUM);
160 
161  /* Construct metapage. */
162  buf = smgr_bulk_get_buf(bulkstate);
164  smgr_bulk_write(bulkstate, SPGIST_METAPAGE_BLKNO, buf, true);
165 
166  /* Likewise for the root page. */
167  buf = smgr_bulk_get_buf(bulkstate);
169  smgr_bulk_write(bulkstate, SPGIST_ROOT_BLKNO, buf, true);
170 
171  /* Likewise for the null-tuples root page. */
172  buf = smgr_bulk_get_buf(bulkstate);
174  smgr_bulk_write(bulkstate, SPGIST_NULL_BLKNO, buf, true);
175 
176  smgr_bulk_finish(bulkstate);
177 }
Pointer Page
Definition: bufpage.h:78
void smgr_bulk_write(BulkWriteState *bulkstate, BlockNumber blocknum, BulkWriteBuffer buf, bool page_std)
Definition: bulk_write.c:271
BulkWriteBuffer smgr_bulk_get_buf(BulkWriteState *bulkstate)
Definition: bulk_write.c:295
void smgr_bulk_finish(BulkWriteState *bulkstate)
Definition: bulk_write.c:129
BulkWriteState * smgr_bulk_start_rel(Relation rel, ForkNumber forknum)
Definition: bulk_write.c:86
static char * buf
Definition: pg_test_fsync.c:73
@ INIT_FORKNUM
Definition: relpath.h:53
void SpGistInitPage(Page page, uint16 f)
Definition: spgutils.c:689

References buf, INIT_FORKNUM, smgr_bulk_finish(), smgr_bulk_get_buf(), smgr_bulk_start_rel(), smgr_bulk_write(), SPGIST_LEAF, SPGIST_METAPAGE_BLKNO, SPGIST_NULL_BLKNO, SPGIST_NULLS, SPGIST_ROOT_BLKNO, SpGistInitMetapage(), and SpGistInitPage().

Referenced by spghandler().

◆ spgbulkdelete()

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

Definition at line 905 of file spgvacuum.c.

907 {
908  spgBulkDeleteState bds;
909 
910  /* allocate stats if first time through, else re-use existing struct */
911  if (stats == NULL)
913  bds.info = info;
914  bds.stats = stats;
915  bds.callback = callback;
916  bds.callback_state = callback_state;
917 
918  spgvacuumscan(&bds);
919 
920  return stats;
921 }
static void spgvacuumscan(spgBulkDeleteState *bds)
Definition: spgvacuum.c:793
IndexBulkDeleteResult * stats
Definition: spgvacuum.c:44
IndexBulkDeleteCallback callback
Definition: spgvacuum.c:45
void * callback_state
Definition: spgvacuum.c:46
IndexVacuumInfo * info
Definition: spgvacuum.c:43
static void callback(struct sockaddr *addr, struct sockaddr *mask, void *unused)
Definition: test_ifaddrs.c:46

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

Referenced by spghandler().

◆ spgcanreturn()

bool spgcanreturn ( Relation  index,
int  attno 
)

Definition at line 1083 of file spgscan.c.

1084 {
1085  SpGistCache *cache;
1086 
1087  /* INCLUDE attributes can always be fetched for index-only scans */
1088  if (attno > 1)
1089  return true;
1090 
1091  /* We can do it if the opclass config function says so */
1092  cache = spgGetCache(index);
1093 
1094  return cache->config.canReturnData;
1095 }
SpGistCache * spgGetCache(Relation index)
Definition: spgutils.c:182
spgConfigOut config
bool canReturnData
Definition: spgist.h:46

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

Referenced by spghandler().

◆ spgendscan()

void spgendscan ( IndexScanDesc  scan)

Definition at line 429 of file spgscan.c.

430 {
432 
435 
436  if (so->keyData)
437  pfree(so->keyData);
438 
439  if (so->state.leafTupDesc &&
442 
443  if (so->state.deadTupleStorage)
445 
446  if (scan->numberOfOrderBys > 0)
447  {
448  pfree(so->orderByTypes);
450  pfree(so->zeroDistances);
451  pfree(so->infDistances);
452  pfree(scan->xs_orderbyvals);
453  pfree(scan->xs_orderbynulls);
454  }
455 
456  pfree(so);
457 }
void pfree(void *pointer)
Definition: mcxt.c:1520
#define RelationGetDescr(relation)
Definition: rel.h:531
Relation index
TupleDesc leafTupDesc
char * deadTupleStorage
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:331

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

Referenced by spghandler().

◆ spggetbitmap()

int64 spggetbitmap ( IndexScanDesc  scan,
TIDBitmap tbm 
)

Definition at line 942 of file spgscan.c.

943 {
945 
946  /* Copy want_itup to *so so we don't need to pass it around separately */
947  so->want_itup = false;
948 
949  so->tbm = tbm;
950  so->ntids = 0;
951 
952  spgWalk(scan->indexRelation, so, true, storeBitmap);
953 
954  return so->ntids;
955 }
static void spgWalk(Relation index, SpGistScanOpaque so, bool scanWholeIndex, storeRes_func storeRes)
Definition: spgscan.c:817
static void storeBitmap(SpGistScanOpaque so, ItemPointer heapPtr, Datum leafValue, bool isnull, SpGistLeafTuple leafTuple, bool recheck, bool recheckDistances, double *distances)
Definition: spgscan.c:931

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

Referenced by spghandler().

◆ spggettuple()

bool spggettuple ( IndexScanDesc  scan,
ScanDirection  dir 
)

Definition at line 1026 of file spgscan.c.

1027 {
1029 
1030  if (dir != ForwardScanDirection)
1031  elog(ERROR, "SP-GiST only supports forward scan direction");
1032 
1033  /* Copy want_itup to *so so we don't need to pass it around separately */
1034  so->want_itup = scan->xs_want_itup;
1035 
1036  for (;;)
1037  {
1038  if (so->iPtr < so->nPtrs)
1039  {
1040  /* continuing to return reported tuples */
1041  scan->xs_heaptid = so->heapPtrs[so->iPtr];
1042  scan->xs_recheck = so->recheck[so->iPtr];
1043  scan->xs_hitup = so->reconTups[so->iPtr];
1044 
1045  if (so->numberOfOrderBys > 0)
1047  so->distances[so->iPtr],
1048  so->recheckDistances[so->iPtr]);
1049  so->iPtr++;
1050  return true;
1051  }
1052 
1053  if (so->numberOfOrderBys > 0)
1054  {
1055  /* Must pfree distances to avoid memory leak */
1056  int i;
1057 
1058  for (i = 0; i < so->nPtrs; i++)
1059  if (so->distances[i])
1060  pfree(so->distances[i]);
1061  }
1062 
1063  if (so->want_itup)
1064  {
1065  /* Must pfree reconstructed tuples to avoid memory leak */
1066  int i;
1067 
1068  for (i = 0; i < so->nPtrs; i++)
1069  pfree(so->reconTups[i]);
1070  }
1071  so->iPtr = so->nPtrs = 0;
1072 
1073  spgWalk(scan->indexRelation, so, false, storeGettuple);
1074 
1075  if (so->nPtrs == 0)
1076  break; /* must have completed scan */
1077  }
1078 
1079  return false;
1080 }
void index_store_float8_orderby_distances(IndexScanDesc scan, Oid *orderByTypes, IndexOrderByDistance *distances, bool recheckOrderBy)
Definition: indexam.c:929
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
@ ForwardScanDirection
Definition: sdir.h:28
static void storeGettuple(SpGistScanOpaque so, ItemPointer heapPtr, Datum leafValue, bool isnull, SpGistLeafTuple leafTuple, bool recheck, bool recheckDistances, double *nonNullDistances)
Definition: spgscan.c:959
HeapTuple xs_hitup
Definition: relscan.h:144
ItemPointerData xs_heaptid
Definition: relscan.h:147
HeapTuple reconTups[MaxIndexTuplesPerPage]
ItemPointerData heapPtrs[MaxIndexTuplesPerPage]
bool recheckDistances[MaxIndexTuplesPerPage]
IndexOrderByDistance * distances[MaxIndexTuplesPerPage]
bool recheck[MaxIndexTuplesPerPage]

References SpGistScanOpaqueData::distances, elog, ERROR, ForwardScanDirection, SpGistScanOpaqueData::heapPtrs, i, if(), 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, and IndexScanDescData::xs_want_itup.

Referenced by spghandler().

◆ spginsert()

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

Definition at line 183 of file spginsert.c.

188 {
189  SpGistState spgstate;
190  MemoryContext oldCtx;
191  MemoryContext insertCtx;
192 
194  "SP-GiST insert temporary context",
196  oldCtx = MemoryContextSwitchTo(insertCtx);
197 
198  initSpGistState(&spgstate, index);
199 
200  /*
201  * We might have to repeat spgdoinsert() multiple times, if conflicts
202  * occur with concurrent insertions. If so, reset the insertCtx each time
203  * to avoid cumulative memory consumption. That means we also have to
204  * redo initSpGistState(), but it's cheap enough not to matter.
205  */
206  while (!spgdoinsert(index, &spgstate, ht_ctid, values, isnull))
207  {
208  MemoryContextReset(insertCtx);
209  initSpGistState(&spgstate, index);
210  }
211 
213 
214  MemoryContextSwitchTo(oldCtx);
215  MemoryContextDelete(insertCtx);
216 
217  /* return false since we've not done any unique check */
218  return false;
219 }
static Datum values[MAXATTR]
Definition: bootstrap.c:152
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:383
MemoryContextSwitchTo(old_ctx)
bool spgdoinsert(Relation index, SpGistState *state, ItemPointer heapPtr, Datum *datums, bool *isnulls)
Definition: spgdoinsert.c:1914

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

Referenced by spghandler().

◆ spgoptions()

bytea* spgoptions ( Datum  reloptions,
bool  validate 
)

Definition at line 740 of file spgutils.c.

741 {
742  static const relopt_parse_elt tab[] = {
743  {"fillfactor", RELOPT_TYPE_INT, offsetof(SpGistOptions, fillfactor)},
744  };
745 
746  return (bytea *) build_reloptions(reloptions, validate,
748  sizeof(SpGistOptions),
749  tab, lengthof(tab));
750 }
#define lengthof(array)
Definition: c.h:788
int fillfactor
Definition: pgbench.c:187
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:1908
@ RELOPT_KIND_SPGIST
Definition: reloptions.h:50
@ RELOPT_TYPE_INT
Definition: reloptions.h:32
Definition: c.h:687

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

Referenced by spghandler().

◆ spgrescan()

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

Definition at line 380 of file spgscan.c.

382 {
384 
385  /* copy scankeys into local storage */
386  if (scankey && scan->numberOfKeys > 0)
387  memmove(scan->keyData, scankey,
388  scan->numberOfKeys * sizeof(ScanKeyData));
389 
390  /* initialize order-by data if needed */
391  if (orderbys && scan->numberOfOrderBys > 0)
392  {
393  int i;
394 
395  memmove(scan->orderByData, orderbys,
396  scan->numberOfOrderBys * sizeof(ScanKeyData));
397 
398  for (i = 0; i < scan->numberOfOrderBys; i++)
399  {
400  ScanKey skey = &scan->orderByData[i];
401 
402  /*
403  * Look up the datatype returned by the original ordering
404  * operator. SP-GiST always uses a float8 for the distance
405  * function, but the ordering operator could be anything else.
406  *
407  * XXX: The distance function is only allowed to be lossy if the
408  * ordering operator's result type is float4 or float8. Otherwise
409  * we don't know how to return the distance to the executor. But
410  * we cannot check that here, as we won't know if the distance
411  * function is lossy until it returns *recheck = true for the
412  * first time.
413  */
415  }
416  }
417 
418  /* preprocess scankeys, set up the representation in *so */
419  spgPrepareScanKeys(scan);
420 
421  /* set up starting queue entries */
423 
424  /* count an indexscan for stats */
426 }
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1633
#define pgstat_count_index_scan(rel)
Definition: pgstat.h:625
static void resetSpGistScanOpaque(SpGistScanOpaque so)
Definition: spgscan.c:154
static void spgPrepareScanKeys(IndexScanDesc scan)
Definition: spgscan.c:208
Oid fn_oid
Definition: fmgr.h:59
struct ScanKeyData * keyData
Definition: relscan.h:122
struct ScanKeyData * orderByData
Definition: relscan.h:123
FmgrInfo sk_func
Definition: skey.h:71

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

Referenced by spghandler().

◆ spgvacuumcleanup()

IndexBulkDeleteResult* spgvacuumcleanup ( IndexVacuumInfo info,
IndexBulkDeleteResult stats 
)

Definition at line 936 of file spgvacuum.c.

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

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().

◆ spgvalidate()

bool spgvalidate ( Oid  opclassoid)

Definition at line 39 of file spgvalidate.c.

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

References spgConfigIn::attType, check_amop_signature(), check_amoptsproc_signature(), check_amproc_signature(), 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(), 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_OPTIONS_PROC, SPGIST_PICKSPLIT_PROC, SPGISTNProc, and catctup::tuple.

Referenced by spghandler().