PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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

◆ spgChooseOut

◆ spgChooseResultType

◆ spgConfigIn

◆ 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 
)
extern

Definition at line 323 of file spgvalidate.c.

327{
328 ListCell *lc;
329
330 /*
331 * Operator members of an SP-GiST opfamily should never have hard
332 * dependencies, since their connection to the opfamily depends only on
333 * what the support functions think, and that can be altered. For
334 * consistency, we make all soft dependencies point to the opfamily,
335 * though a soft dependency on the opclass would work as well in the
336 * CREATE OPERATOR CLASS case.
337 */
338 foreach(lc, operators)
339 {
341
342 op->ref_is_hard = false;
343 op->ref_is_family = true;
344 op->refobjid = opfamilyoid;
345 }
346
347 /*
348 * Required support functions should have hard dependencies. Preferably
349 * those are just dependencies on the opclass, but if we're in ALTER
350 * OPERATOR FAMILY, we leave the dependency pointing at the whole
351 * opfamily. (Given that SP-GiST opclasses generally don't share
352 * opfamilies, it seems unlikely to be worth working harder.)
353 */
354 foreach(lc, functions)
355 {
357
358 switch (op->number)
359 {
365 /* Required support function */
366 op->ref_is_hard = true;
367 break;
370 /* Optional, so force it to be a soft family dependency */
371 op->ref_is_hard = false;
372 op->ref_is_family = true;
373 op->refobjid = opfamilyoid;
374 break;
375 default:
378 errmsg("support function number %d is invalid for access method %s",
379 op->number, "spgist")));
380 break;
381 }
382 }
383}
int errcode(int sqlerrcode)
Definition elog.c:863
int errmsg(const char *fmt,...)
Definition elog.c:1080
#define ERROR
Definition elog.h:39
#define ereport(elevel,...)
Definition elog.h:150
#define lfirst(lc)
Definition pg_list.h:172
static int fb(int x)
static const struct fns functions
Definition regcomp.c:358
#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:98
bool ref_is_family
Definition amapi.h:97
bool ref_is_hard
Definition amapi.h:96

References ereport, errcode(), errmsg(), ERROR, fb(), 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 
)
extern

Definition at line 305 of file spgscan.c.

306{
307 IndexScanDesc scan;
309 int i;
310
311 scan = RelationGetIndexScan(rel, keysz, orderbysz);
312
314 if (keysz > 0)
315 so->keyData = palloc_array(ScanKeyData, keysz);
316 else
317 so->keyData = NULL;
318 initSpGistState(&so->state, scan->indexRelation);
319
321 "SP-GiST search temporary context",
324 "SP-GiST traversal-value context",
326
327 /*
328 * Set up reconTupDesc and xs_hitupdesc in case it's an index-only scan,
329 * making sure that the key column is shown as being of type attType.
330 * (It's rather annoying to do this work when it might be wasted, but for
331 * most opclasses we can re-use the index reldesc instead of making one.)
332 */
333 so->reconTupDesc = scan->xs_hitupdesc =
334 getSpGistTupleDesc(rel, &so->state.attType);
335
336 /* Allocate various arrays needed for order-by scans */
337 if (scan->numberOfOrderBys > 0)
338 {
339 /* This will be filled in spgrescan, but allocate the space here */
340 so->orderByTypes = palloc_array(Oid, scan->numberOfOrderBys);
341 so->nonNullOrderByOffsets = palloc_array(int, scan->numberOfOrderBys);
342
343 /* These arrays have constant contents, so we can fill them now */
344 so->zeroDistances = palloc_array(double, scan->numberOfOrderBys);
345 so->infDistances = palloc_array(double, scan->numberOfOrderBys);
346
347 for (i = 0; i < scan->numberOfOrderBys; i++)
348 {
349 so->zeroDistances[i] = 0.0;
350 so->infDistances[i] = get_float8_infinity();
351 }
352
354 scan->xs_orderbynulls = palloc_array(bool, scan->numberOfOrderBys);
355 memset(scan->xs_orderbynulls, true,
356 sizeof(bool) * scan->numberOfOrderBys);
357 }
358
359 fmgr_info_copy(&so->innerConsistentFn,
362
363 fmgr_info_copy(&so->leafConsistentFn,
366
367 so->indexCollation = rel->rd_indcollation[0];
368
369 scan->opaque = so;
370
371 return scan;
372}
#define palloc_array(type, count)
Definition fe_memutils.h:76
#define palloc0_array(type, count)
Definition fe_memutils.h:77
#define palloc0_object(type)
Definition fe_memutils.h:75
static float8 get_float8_infinity(void)
Definition float.h:65
void fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo, MemoryContext destcxt)
Definition fmgr.c:581
IndexScanDesc RelationGetIndexScan(Relation indexRelation, int nkeys, int norderbys)
Definition genam.c:80
FmgrInfo * index_getprocinfo(Relation irel, AttrNumber attnum, uint16 procnum)
Definition indexam.c:917
int i
Definition isn.c:77
MemoryContext CurrentMemoryContext
Definition mcxt.c:160
#define AllocSetContextCreate
Definition memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition memutils.h:160
uint64_t Datum
Definition postgres.h:70
unsigned int Oid
void initSpGistState(SpGistState *state, Relation index)
Definition spgutils.c:349
TupleDesc getSpGistTupleDesc(Relation index, SpGistTypeDesc *keyType)
Definition spgutils.c:316
bool * xs_orderbynulls
Definition relscan.h:188
struct TupleDescData * xs_hitupdesc
Definition relscan.h:171
Relation indexRelation
Definition relscan.h:138
Datum * xs_orderbyvals
Definition relscan.h:187
Oid * rd_indcollation
Definition rel.h:217

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, CurrentMemoryContext, fb(), fmgr_info_copy(), get_float8_infinity(), getSpGistTupleDesc(), i, index_getprocinfo(), IndexScanDescData::indexRelation, initSpGistState(), IndexScanDescData::numberOfOrderBys, IndexScanDescData::opaque, palloc0_array, palloc0_object, palloc_array, RelationData::rd_indcollation, RelationGetIndexScan(), SPGIST_INNER_CONSISTENT_PROC, SPGIST_LEAF_CONSISTENT_PROC, IndexScanDescData::xs_hitupdesc, IndexScanDescData::xs_orderbynulls, and IndexScanDescData::xs_orderbyvals.

Referenced by spghandler().

◆ spgbuild()

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

Definition at line 73 of file spginsert.c.

74{
75 IndexBuildResult *result;
76 double reltuples;
81
83 elog(ERROR, "index \"%s\" already contains data",
85
86 /*
87 * Initialize the meta page and root pages
88 */
92
96
98
105
106
108
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,
126 NULL);
127
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 */
137 {
140 true);
141 }
142
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:4356
void UnlockReleaseBuffer(Buffer buffer)
Definition bufmgr.c:5518
void MarkBufferDirty(Buffer buffer)
Definition bufmgr.c:3056
#define RelationGetNumberOfBlocks(reln)
Definition bufmgr.h:307
static Page BufferGetPage(Buffer buffer)
Definition bufmgr.h:466
#define Assert(condition)
Definition c.h:873
#define elog(elevel,...)
Definition elog.h:226
void MemoryContextDelete(MemoryContext context)
Definition mcxt.c:472
#define START_CRIT_SECTION()
Definition miscadmin.h:150
#define END_CRIT_SECTION()
Definition miscadmin.h:152
#define RelationGetRelationName(relation)
Definition rel.h:548
#define RelationNeedsWAL(relation)
Definition rel.h:637
@ MAIN_FORKNUM
Definition relpath.h:58
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:451
Buffer SpGistNewBuffer(Relation index)
Definition spgutils.c:395
void SpGistInitBuffer(Buffer b, uint16 f)
Definition spgutils.c:723
void SpGistInitMetapage(Page page)
Definition spgutils.c:733
double heap_tuples
Definition genam.h:38
double index_tuples
Definition genam.h:39
Definition type.h:96
static double table_index_build_scan(Relation table_rel, Relation index_rel, IndexInfo *index_info, bool allow_sync, bool progress, IndexBuildCallback callback, void *callback_state, TableScanDesc scan)
Definition tableam.h:1766
void log_newpage_range(Relation rel, ForkNumber forknum, BlockNumber startblk, BlockNumber endblk, bool page_std)

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, BufferGetBlockNumber(), BufferGetPage(), CurrentMemoryContext, elog, END_CRIT_SECTION, ERROR, fb(), IndexBuildResult::heap_tuples, IndexBuildResult::index_tuples, initSpGistState(), log_newpage_range(), MAIN_FORKNUM, MarkBufferDirty(), MemoryContextDelete(), palloc0_object, RelationGetNumberOfBlocks, RelationGetRelationName, RelationNeedsWAL, SPGIST_LEAF, SPGIST_METAPAGE_BLKNO, SPGIST_NULL_BLKNO, SPGIST_NULLS, SPGIST_ROOT_BLKNO, spgistBuildCallback(), SpGistInitBuffer(), SpGistInitMetapage(), SpGistNewBuffer(), SpGistUpdateMetaPage(), START_CRIT_SECTION, table_index_build_scan(), and UnlockReleaseBuffer().

Referenced by spghandler().

◆ spgbuildempty()

void spgbuildempty ( Relation  index)
extern

Definition at line 154 of file spginsert.c.

155{
156 BulkWriteState *bulkstate;
158
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}
PageData * Page
Definition bufpage.h:81
BulkWriteState * smgr_bulk_start_rel(Relation rel, ForkNumber forknum)
Definition bulk_write.c:87
void smgr_bulk_write(BulkWriteState *bulkstate, BlockNumber blocknum, BulkWriteBuffer buf, bool page_std)
Definition bulk_write.c:323
BulkWriteBuffer smgr_bulk_get_buf(BulkWriteState *bulkstate)
Definition bulk_write.c:347
void smgr_bulk_finish(BulkWriteState *bulkstate)
Definition bulk_write.c:130
static char buf[DEFAULT_XLOG_SEG_SIZE]
@ INIT_FORKNUM
Definition relpath.h:61
void SpGistInitPage(Page page, uint16 f)
Definition spgutils.c:709

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 
)
extern

Definition at line 950 of file spgvacuum.c.

952{
954
955 /* allocate stats if first time through, else re-use existing struct */
956 if (stats == NULL)
958 bds.info = info;
959 bds.stats = stats;
960 bds.callback = callback;
961 bds.callback_state = callback_state;
962
964
965 return stats;
966}
static void spgvacuumscan(spgBulkDeleteState *bds)
Definition spgvacuum.c:800
static void callback(struct sockaddr *addr, struct sockaddr *mask, void *unused)

References callback(), fb(), palloc0_object, and spgvacuumscan().

Referenced by spghandler().

◆ spgcanreturn()

bool spgcanreturn ( Relation  index,
int  attno 
)
extern

Definition at line 1078 of file spgscan.c.

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

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

Referenced by spghandler().

◆ spgendscan()

void spgendscan ( IndexScanDesc  scan)
extern

Definition at line 424 of file spgscan.c.

425{
427
428 MemoryContextDelete(so->tempCxt);
429 MemoryContextDelete(so->traversalCxt);
430
431 if (so->keyData)
432 pfree(so->keyData);
433
434 if (so->state.leafTupDesc &&
435 so->state.leafTupDesc != RelationGetDescr(so->state.index))
436 FreeTupleDesc(so->state.leafTupDesc);
437
438 if (so->state.deadTupleStorage)
439 pfree(so->state.deadTupleStorage);
440
441 if (scan->numberOfOrderBys > 0)
442 {
443 pfree(so->orderByTypes);
444 pfree(so->nonNullOrderByOffsets);
445 pfree(so->zeroDistances);
446 pfree(so->infDistances);
447 pfree(scan->xs_orderbyvals);
448 pfree(scan->xs_orderbynulls);
449 }
450
451 pfree(so);
452}
void pfree(void *pointer)
Definition mcxt.c:1616
#define RelationGetDescr(relation)
Definition rel.h:540
SpGistScanOpaqueData * SpGistScanOpaque
void FreeTupleDesc(TupleDesc tupdesc)
Definition tupdesc.c:502

References fb(), FreeTupleDesc(), MemoryContextDelete(), IndexScanDescData::numberOfOrderBys, IndexScanDescData::opaque, pfree(), RelationGetDescr, IndexScanDescData::xs_orderbynulls, and IndexScanDescData::xs_orderbyvals.

Referenced by spghandler().

◆ spggetbitmap()

int64 spggetbitmap ( IndexScanDesc  scan,
TIDBitmap tbm 
)
extern

Definition at line 937 of file spgscan.c.

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

References fb(), IndexScanDescData::indexRelation, IndexScanDescData::opaque, spgWalk(), and storeBitmap().

Referenced by spghandler().

◆ spggettuple()

bool spggettuple ( IndexScanDesc  scan,
ScanDirection  dir 
)
extern

Definition at line 1021 of file spgscan.c.

1022{
1024
1025 if (dir != ForwardScanDirection)
1026 elog(ERROR, "SP-GiST only supports forward scan direction");
1027
1028 /* Copy want_itup to *so so we don't need to pass it around separately */
1029 so->want_itup = scan->xs_want_itup;
1030
1031 for (;;)
1032 {
1033 if (so->iPtr < so->nPtrs)
1034 {
1035 /* continuing to return reported tuples */
1036 scan->xs_heaptid = so->heapPtrs[so->iPtr];
1037 scan->xs_recheck = so->recheck[so->iPtr];
1038 scan->xs_hitup = so->reconTups[so->iPtr];
1039
1040 if (so->numberOfOrderBys > 0)
1041 index_store_float8_orderby_distances(scan, so->orderByTypes,
1042 so->distances[so->iPtr],
1043 so->recheckDistances[so->iPtr]);
1044 so->iPtr++;
1045 return true;
1046 }
1047
1048 if (so->numberOfOrderBys > 0)
1049 {
1050 /* Must pfree distances to avoid memory leak */
1051 int i;
1052
1053 for (i = 0; i < so->nPtrs; i++)
1054 if (so->distances[i])
1055 pfree(so->distances[i]);
1056 }
1057
1058 if (so->want_itup)
1059 {
1060 /* Must pfree reconstructed tuples to avoid memory leak */
1061 int i;
1062
1063 for (i = 0; i < so->nPtrs; i++)
1064 pfree(so->reconTups[i]);
1065 }
1066 so->iPtr = so->nPtrs = 0;
1067
1068 spgWalk(scan->indexRelation, so, false, storeGettuple);
1069
1070 if (so->nPtrs == 0)
1071 break; /* must have completed scan */
1072 }
1073
1074 return false;
1075}
void index_store_float8_orderby_distances(IndexScanDesc scan, Oid *orderByTypes, IndexOrderByDistance *distances, bool recheckOrderBy)
Definition indexam.c:985
@ 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:954
HeapTuple xs_hitup
Definition relscan.h:170
ItemPointerData xs_heaptid
Definition relscan.h:173

References elog, ERROR, fb(), ForwardScanDirection, i, index_store_float8_orderby_distances(), IndexScanDescData::indexRelation, IndexScanDescData::opaque, pfree(), spgWalk(), storeGettuple(), 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 
)
extern

Definition at line 183 of file spginsert.c.

188{
189 SpGistState spgstate;
192
194 "SP-GiST insert temporary context",
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 {
209 initSpGistState(&spgstate, index);
210 }
211
213
216
217 /* return false since we've not done any unique check */
218 return false;
219}
static Datum values[MAXATTR]
Definition bootstrap.c:155
void MemoryContextReset(MemoryContext context)
Definition mcxt.c:403
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
bool spgdoinsert(Relation index, SpGistState *state, const ItemPointerData *heapPtr, const Datum *datums, const bool *isnulls)

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

Referenced by spghandler().

◆ spgoptions()

bytea * spgoptions ( Datum  reloptions,
bool  validate 
)
extern

Definition at line 760 of file spgutils.c.

761{
762 static const relopt_parse_elt tab[] = {
764 };
765
766 return (bytea *) build_reloptions(reloptions, validate,
768 sizeof(SpGistOptions),
769 tab, lengthof(tab));
770}
static bool validate(Port *port, const char *auth)
Definition auth-oauth.c:638
#define lengthof(array)
Definition c.h:803
static int fillfactor
Definition pgbench.c:188
void * build_reloptions(Datum reloptions, bool validate, relopt_kind kind, Size relopt_struct_size, const relopt_parse_elt *relopt_elems, int num_relopt_elems)
@ RELOPT_KIND_SPGIST
Definition reloptions.h:51
@ RELOPT_TYPE_INT
Definition reloptions.h:33
Definition c.h:706

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

Referenced by spghandler().

◆ spgrescan()

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

Definition at line 375 of file spgscan.c.

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

References fb(), get_func_rettype(), i, IndexScanDescData::indexRelation, IndexScanDescData::instrument, IndexScanDescData::keyData, IndexScanInstrumentation::nsearches, IndexScanDescData::numberOfKeys, IndexScanDescData::numberOfOrderBys, IndexScanDescData::opaque, IndexScanDescData::orderByData, pgstat_count_index_scan, resetSpGistScanOpaque(), and spgPrepareScanKeys().

Referenced by spghandler().

◆ spgvacuumcleanup()

IndexBulkDeleteResult * spgvacuumcleanup ( IndexVacuumInfo info,
IndexBulkDeleteResult stats 
)
extern

Definition at line 981 of file spgvacuum.c.

982{
984
985 /* No-op in ANALYZE ONLY mode */
986 if (info->analyze_only)
987 return stats;
988
989 /*
990 * We don't need to scan the index if there was a preceding bulkdelete
991 * pass. Otherwise, make a pass that won't delete any live tuples, but
992 * might still accomplish useful stuff with redirect/placeholder cleanup
993 * and/or FSM housekeeping, and in any case will provide stats.
994 */
995 if (stats == NULL)
996 {
998 bds.info = info;
999 bds.stats = stats;
1000 bds.callback = dummy_callback;
1001 bds.callback_state = NULL;
1002
1004 }
1005
1006 /*
1007 * It's quite possible for us to be fooled by concurrent tuple moves into
1008 * double-counting some index tuples, so disbelieve any total that exceeds
1009 * the underlying heap's count ... if we know that accurately. Otherwise
1010 * this might just make matters worse.
1011 */
1012 if (!info->estimated_count)
1013 {
1014 if (stats->num_index_tuples > info->num_heap_tuples)
1015 stats->num_index_tuples = info->num_heap_tuples;
1016 }
1017
1018 return stats;
1019}
static bool dummy_callback(ItemPointer itemptr, void *state)
Definition spgvacuum.c:970
double num_index_tuples
Definition genam.h:85
double num_heap_tuples
Definition genam.h:58
bool analyze_only
Definition genam.h:54
bool estimated_count
Definition genam.h:56

References IndexVacuumInfo::analyze_only, dummy_callback(), IndexVacuumInfo::estimated_count, fb(), IndexVacuumInfo::num_heap_tuples, IndexBulkDeleteResult::num_index_tuples, palloc0_object, and spgvacuumscan().

Referenced by spghandler().

◆ spgvalidate()

bool spgvalidate ( Oid  opclassoid)
extern

Definition at line 38 of file spgvalidate.c.

39{
40 bool result = true;
44 Oid opcintype;
46 char *opclassname;
47 char *opfamilyname;
49 *oprlist;
52 int i;
53 ListCell *lc;
59
60 /* Fetch opclass information */
63 elog(ERROR, "cache lookup failed for operator class %u", opclassoid);
65
66 opfamilyoid = classform->opcfamily;
67 opcintype = classform->opcintype;
68 opckeytype = classform->opckeytype;
69 opclassname = NameStr(classform->opcname);
70
71 /* Fetch opfamily information */
72 opfamilyname = get_opfamily_name(opfamilyoid, false);
73
74 /* Fetch all operators and support functions of the opfamily */
78
79 /* Check individual support functions */
80 for (i = 0; i < proclist->n_members; i++)
81 {
82 HeapTuple proctup = &proclist->members[i]->tuple;
84 bool ok;
85
86 /*
87 * All SP-GiST support functions should be registered with matching
88 * left/right types
89 */
90 if (procform->amproclefttype != procform->amprocrighttype)
91 {
94 errmsg("operator family \"%s\" of access method %s contains support function %s with different left and right input types",
95 opfamilyname, "spgist",
96 format_procedure(procform->amproc))));
97 result = false;
98 }
99
100 /* Check procedure numbers and function signatures */
101 switch (procform->amprocnum)
102 {
104 ok = check_amproc_signature(procform->amproc, VOIDOID, true,
105 2, 2, INTERNALOID, INTERNALOID);
106 configIn.attType = procform->amproclefttype;
107 memset(&configOut, 0, sizeof(configOut));
108
112
113 configOutLefttype = procform->amproclefttype;
114 configOutRighttype = procform->amprocrighttype;
115
116 /* Default leaf type is opckeytype or input type */
119 else
120 configOutLeafType = procform->amproclefttype;
121
122 /* If some other leaf datum type is specified, warn */
123 if (OidIsValid(configOut.leafType) &&
124 configOutLeafType != configOut.leafType)
125 {
128 errmsg("SP-GiST leaf data type %s does not match declared type %s",
129 format_type_be(configOut.leafType),
131 result = false;
132 configOutLeafType = configOut.leafType;
133 }
134
135 /*
136 * When leaf and attribute types are the same, compress
137 * function is not required and we set corresponding bit in
138 * functionset for later group consistency check.
139 */
140 if (configOutLeafType == configIn.attType)
141 {
142 foreach(lc, grouplist)
143 {
144 OpFamilyOpFuncGroup *group = lfirst(lc);
145
146 if (group->lefttype == procform->amproclefttype &&
147 group->righttype == procform->amprocrighttype)
148 {
149 group->functionset |=
151 break;
152 }
153 }
154 }
155 break;
159 ok = check_amproc_signature(procform->amproc, VOIDOID, true,
160 2, 2, INTERNALOID, INTERNALOID);
161 break;
163 ok = check_amproc_signature(procform->amproc, BOOLOID, true,
164 2, 2, INTERNALOID, INTERNALOID);
165 break;
167 if (configOutLefttype != procform->amproclefttype ||
168 configOutRighttype != procform->amprocrighttype)
169 ok = false;
170 else
172 configOutLeafType, true,
173 1, 1, procform->amproclefttype);
174 break;
177 break;
178 default:
181 errmsg("operator family \"%s\" of access method %s contains function %s with invalid support number %d",
182 opfamilyname, "spgist",
183 format_procedure(procform->amproc),
184 procform->amprocnum)));
185 result = false;
186 continue; /* don't want additional message */
187 }
188
189 if (!ok)
190 {
193 errmsg("operator family \"%s\" of access method %s contains function %s with wrong signature for support number %d",
194 opfamilyname, "spgist",
195 format_procedure(procform->amproc),
196 procform->amprocnum)));
197 result = false;
198 }
199 }
200
201 /* Check individual operators */
202 for (i = 0; i < oprlist->n_members; i++)
203 {
204 HeapTuple oprtup = &oprlist->members[i]->tuple;
207
208 /* TODO: Check that only allowed strategy numbers exist */
209 if (oprform->amopstrategy < 1 || oprform->amopstrategy > 63)
210 {
213 errmsg("operator family \"%s\" of access method %s contains operator %s with invalid strategy number %d",
214 opfamilyname, "spgist",
215 format_operator(oprform->amopopr),
216 oprform->amopstrategy)));
217 result = false;
218 }
219
220 /* spgist supports ORDER BY operators */
221 if (oprform->amoppurpose != AMOP_SEARCH)
222 {
223 /* ... and operator result must match the claimed btree opfamily */
225 if (!opfamily_can_sort_type(oprform->amopsortfamily, op_rettype))
226 {
229 errmsg("operator family \"%s\" of access method %s contains invalid ORDER BY specification for operator %s",
230 opfamilyname, "spgist",
231 format_operator(oprform->amopopr))));
232 result = false;
233 }
234 }
235 else
237
238 /* Check operator signature --- same for all spgist strategies */
240 oprform->amoplefttype,
241 oprform->amoprighttype))
242 {
245 errmsg("operator family \"%s\" of access method %s contains operator %s with wrong signature",
246 opfamilyname, "spgist",
247 format_operator(oprform->amopopr))));
248 result = false;
249 }
250 }
251
252 /* Now check for inconsistent groups of operators/functions */
254 foreach(lc, grouplist)
255 {
257
258 /* Remember the group exactly matching the test opclass */
259 if (thisgroup->lefttype == opcintype &&
260 thisgroup->righttype == opcintype)
262
263 /*
264 * Complain if there are any datatype pairs with functions but no
265 * operators. This is about the best we can do for now to detect
266 * missing operators.
267 */
268 if (thisgroup->operatorset == 0)
269 {
272 errmsg("operator family \"%s\" of access method %s is missing operator(s) for types %s and %s",
273 opfamilyname, "spgist",
274 format_type_be(thisgroup->lefttype),
275 format_type_be(thisgroup->righttype))));
276 result = false;
277 }
278
279 /*
280 * Complain if we're missing functions for any datatype, remembering
281 * that SP-GiST doesn't use cross-type support functions.
282 */
283 if (thisgroup->lefttype != thisgroup->righttype)
284 continue;
285
286 for (i = 1; i <= SPGISTNProc; i++)
287 {
288 if ((thisgroup->functionset & (((uint64) 1) << i)) != 0)
289 continue; /* got it */
290 if (i == SPGIST_OPTIONS_PROC)
291 continue; /* optional method */
294 errmsg("operator family \"%s\" of access method %s is missing support function %d for type %s",
295 opfamilyname, "spgist", i,
296 format_type_be(thisgroup->lefttype))));
297 result = false;
298 }
299 }
300
301 /* Check that the originally-named opclass is supported */
302 /* (if group is there, we already checked it adequately above) */
303 if (!opclassgroup)
304 {
307 errmsg("operator class \"%s\" of access method %s is missing operator(s)",
308 opclassname, "spgist")));
309 result = false;
310 }
311
315
316 return result;
317}
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:765
uint64_t uint64
Definition c.h:547
#define OidIsValid(objectId)
Definition c.h:788
void ReleaseCatCacheList(CatCList *list)
Definition catcache.c:2114
#define INFO
Definition elog.h:34
#define OidFunctionCall2(functionId, arg1, arg2)
Definition fmgr.h:724
char * format_type_be(Oid type_oid)
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
Oid get_op_rettype(Oid opno)
Definition lsyscache.c:1483
char * get_opfamily_name(Oid opfid, bool missing_ok)
Definition lsyscache.c:1403
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
static Datum PointerGetDatum(const void *X)
Definition postgres.h:352
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:262
#define InvalidOid
char * format_procedure(Oid procedure_oid)
Definition regproc.c:305
char * format_operator(Oid operator_oid)
Definition regproc.c:801
#define SPGISTNProc
Definition spgist.h:31
Definition pg_list.h:54
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:264
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition syscache.c:220
#define SearchSysCacheList1(cacheId, key1)
Definition syscache.h:127

References check_amop_signature(), check_amoptsproc_signature(), check_amproc_signature(), elog, ereport, errcode(), errmsg(), ERROR, fb(), format_operator(), format_procedure(), format_type_be(), OpFamilyOpFuncGroup::functionset, get_op_rettype(), get_opfamily_name(), GETSTRUCT(), HeapTupleIsValid, i, identify_opfamily_groups(), INFO, InvalidOid, OpFamilyOpFuncGroup::lefttype, lfirst, NameStr, ObjectIdGetDatum(), OidFunctionCall2, OidIsValid, 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, and SPGISTNProc.

Referenced by spghandler().