32#include "utils/fmgrprotos.h"
47 .
type = T_IndexAmRoutine,
52 .amcanorderbyop =
true,
54 .amconsistentequality =
false,
55 .amconsistentordering =
false,
56 .amcanbackward =
false,
58 .amcanmulticol =
false,
59 .amoptionalkey =
true,
60 .amsearcharray =
false,
61 .amsearchnulls =
true,
63 .amclusterable =
false,
65 .amcanparallel =
false,
66 .amcanbuildparallel =
false,
68 .amusemaintenanceworkmem =
false,
69 .amsummarizing =
false,
70 .amparallelvacuumoptions =
77 .aminsertcleanup = NULL,
82 .amgettreeheight = NULL,
85 .ambuildphasename = NULL,
95 .amestimateparallelscan = NULL,
96 .aminitparallelscan = NULL,
97 .amparallelrescan = NULL,
98 .amtranslatestrategy = NULL,
99 .amtranslatecmptype = NULL,
130 Assert(indexcol > 0 && indexcol <= index->rd_index->indnkeyatts);
131 opcintype =
index->rd_opcintype[indexcol - 1];
132 if (!IsPolymorphicType(opcintype))
134 heapcol =
index->rd_index->indkey.values[indexcol - 1];
144 if (
index->rd_indexprs)
145 indexprs =
index->rd_indexprs;
149 for (
int i = 1;
i <=
index->rd_index->indnkeyatts;
i++)
151 if (
index->rd_index->indkey.values[
i - 1] == 0)
154 if (indexpr_item == NULL)
155 elog(
ERROR,
"wrong number of index expressions");
158 indexpr_item =
lnext(indexprs, indexpr_item);
161 elog(
ERROR,
"wrong number of index expressions");
177 desc->
attlen = typtup->typlen;
193 if (
index->rd_amcache == NULL)
251 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
252 errmsg(
"compress method must be defined when leaf type is different from input type")));
269 if (
index->rd_rel->relkind != RELKIND_PARTITIONED_INDEX)
280 elog(
ERROR,
"index \"%s\" is not an SP-GiST index",
288 index->rd_amcache = cache;
329 att->atttypid = keyType->
type;
331 att->attlen = keyType->
attlen;
385 state->isBuild =
false;
491#define GET_LUP(c, f) (&(c)->lastUsedPages.cachedPage[((unsigned int) (f)) % SPGIST_CACHED_PAGES])
577 elog(
ERROR,
"desired SPGiST tuple size is too big");
646 if (freeSpace >= needSpace)
785 size =
sizeof(
Datum);
804 memcpy(target, &datum,
sizeof(
Datum));
820 const Datum *datums,
const bool *isnulls)
824 bool needs_null_mask =
false;
825 int natts = tupleDescriptor->
natts;
836 for (
int i = 0;
i < natts;
i++)
840 needs_null_mask =
true;
873 const Datum *datums,
const bool *isnulls)
880 bool needs_null_mask =
false;
881 int natts = tupleDescriptor->
natts;
894 for (
int i = 0;
i < natts;
i++)
898 needs_null_mask =
true;
913 size = hoff + data_size;
930 tp = (
char *) tup + hoff;
947 &tupmask, (
bits8 *) NULL);
965 unsigned short infomask = 0;
978 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
979 errmsg(
"index row requires %zu bytes, maximum size is %zu",
1008 unsigned int prefixSize;
1021 for (
i = 0;
i < nNodes;
i++)
1036 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1037 errmsg(
"SP-GiST inner tuple size %zu exceeds maximum %zu",
1040 errhint(
"Values larger than a buffer page cannot be indexed.")));
1049 elog(
ERROR,
"SPGiST inner tuple header field is too small");
1063 for (
i = 0;
i < nNodes;
i++)
1117 Datum *datums,
bool *isnulls,
bool keyColumnIsNull)
1123 if (keyColumnIsNull && tupleDescriptor->
natts == 1)
1141 tp = (
char *) tup +
SGLTHDRSZ(hasNullsMask);
1146 tp, bp, hasNullsMask);
1174 elog(
ERROR,
"some but not all node labels are null in SPGiST inner tuple");
1185 elog(
ERROR,
"some but not all node labels are null in SPGiST inner tuple");
1225 for (;
i <= maxoff;
i++)
1258 offnum =
PageAddItem(page, item, size, offnum,
false,
false);
1271 *startOffset = offnum + 1;
1274 elog(
PANIC,
"failed to add item of size %zu to SPGiST index page",
1286 elog(
ERROR,
"failed to add item of size %zu to SPGiST index page",
1301 bool *res,
bool *isnull)
1353 if (amopform->amoppurpose == AMOP_ORDER &&
1354 (amopform->amoplefttype == opcintype ||
1355 amopform->amoprighttype == opcintype) &&
@ AMPROP_DISTANCE_ORDERABLE
bool opfamily_can_sort_type(Oid opfamilyoid, Oid datatypeoid)
static bool validate(Port *port, const char *auth)
#define InvalidBlockNumber
BlockNumber BufferGetBlockNumber(Buffer buffer)
void LockBuffer(Buffer buffer, BufferLockMode mode)
Buffer ExtendBufferedRel(BufferManagerRelation bmr, ForkNumber forkNum, BufferAccessStrategy strategy, uint32 flags)
bool ConditionalLockBuffer(Buffer buffer)
void ReleaseBuffer(Buffer buffer)
void UnlockReleaseBuffer(Buffer buffer)
void MarkBufferDirty(Buffer buffer)
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
static Page BufferGetPage(Buffer buffer)
static Size BufferGetPageSize(Buffer buffer)
void PageIndexTupleDelete(Page page, OffsetNumber offnum)
Size PageGetExactFreeSpace(const PageData *page)
void PageInit(Page page, Size pageSize, Size specialSize)
static bool PageIsEmpty(const PageData *page)
PageHeaderData * PageHeader
static bool PageIsNew(const PageData *page)
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
static void * PageGetItem(PageData *page, const ItemIdData *itemId)
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
static OffsetNumber PageGetMaxOffsetNumber(const PageData *page)
#define OidIsValid(objectId)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
#define palloc_array(type, count)
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
#define PG_RETURN_POINTER(x)
Assert(PointerIsAligned(start, uint64))
Size heap_compute_data_size(TupleDesc tupleDesc, const Datum *values, const bool *isnull)
void heap_fill_tuple(TupleDesc tupleDesc, const Datum *values, const bool *isnull, char *data, Size data_size, uint16 *infomask, bits8 *bit)
#define HeapTupleIsValid(tuple)
static void * GETSTRUCT(const HeapTupleData *tuple)
FmgrInfo * index_getprocinfo(Relation irel, AttrNumber attnum, uint16 procnum)
RegProcedure index_getprocid(Relation irel, AttrNumber attnum, uint16 procnum)
BlockNumber GetFreeIndexPage(Relation rel)
void index_deform_tuple_internal(TupleDesc tupleDescriptor, Datum *values, bool *isnull, char *tp, bits8 *bp, int hasnulls)
if(TABLE==NULL||TABLE_index==NULL)
static void ItemPointerSet(ItemPointerData *pointer, BlockNumber blockNumber, OffsetNumber offNum)
static void ItemPointerSetInvalid(ItemPointerData *pointer)
static bool IndexTupleHasNulls(const IndexTupleData *itup)
static Size IndexTupleSize(const IndexTupleData *itup)
bool get_opclass_opfamily_and_input_type(Oid opclass, Oid *opfamily, Oid *opcintype)
Oid get_op_rettype(Oid opno)
Oid get_index_column_opclass(Oid index_oid, int attno)
Oid getBaseType(Oid typid)
Oid get_atttype(Oid relid, AttrNumber attnum)
void * MemoryContextAllocZero(MemoryContext context, Size size)
void * palloc0(Size size)
Oid exprType(const Node *expr)
#define InvalidOffsetNumber
#define FirstOffsetNumber
bool IsBinaryCoercible(Oid srctype, Oid targettype)
FormData_pg_amop * Form_pg_amop
FormData_pg_attribute * Form_pg_attribute
static ListCell * list_head(const List *l)
static ListCell * lnext(const List *l, const ListCell *c)
FormData_pg_type * Form_pg_type
static Datum PointerGetDatum(const void *X)
static Datum ObjectIdGetDatum(Oid X)
static Pointer DatumGetPointer(Datum X)
#define RelationGetDescr(relation)
#define RelationGetRelationName(relation)
#define IndexRelationGetNumberOfAttributes(relation)
#define IndexRelationGetNumberOfKeyAttributes(relation)
List * RelationGetIndexExpressions(Relation relation)
void * build_reloptions(Datum reloptions, bool validate, relopt_kind kind, Size relopt_struct_size, const relopt_parse_elt *relopt_elems, int num_relopt_elems)
void spgcostestimate(PlannerInfo *root, IndexPath *path, double loop_count, Cost *indexStartupCost, Cost *indexTotalCost, Selectivity *indexSelectivity, double *indexCorrelation, double *indexPages)
IndexBuildResult * spgbuild(Relation heap, Relation index, IndexInfo *indexInfo)
bool spginsert(Relation index, Datum *values, bool *isnull, ItemPointer ht_ctid, Relation heapRel, IndexUniqueCheck checkUnique, bool indexUnchanged, IndexInfo *indexInfo)
void spgbuildempty(Relation index)
#define SPGIST_OPTIONS_PROC
#define SPGIST_COMPRESS_PROC
#define SPGIST_CONFIG_PROC
SpGistDeadTupleData * SpGistDeadTuple
#define SGLT_GET_HASNULLMASK(spgLeafTuple)
SpGistInnerTupleData * SpGistInnerTuple
#define SpGistPageStoresNulls(page)
#define SPGIST_PLACEHOLDER
#define SGLT_SET_HASNULLMASK(spgLeafTuple, hasnulls)
#define SGITITERATE(x, i, nt)
#define SpGistGetTargetPageFreeSpace(relation)
#define spgFirstIncludeColumn
#define SpGistPageGetMeta(p)
SpGistNodeTupleData * SpGistNodeTuple
#define SGITMAXPREFIXSIZE
#define SpGistPageIsLeaf(page)
#define SPGIST_METAPAGE_BLKNO
#define SpGistPageIsDeleted(page)
#define SGLTHDRSZ(hasnulls)
#define SGLT_SET_NEXTOFFSET(spgLeafTuple, offsetNumber)
struct SpGistLeafTupleData * SpGistLeafTuple
#define SPGIST_MAGIC_NUMBER
#define SPGIST_CACHED_PAGES
#define GBUF_REQ_NULLS(flags)
#define SPGIST_PAGE_CAPACITY
#define SpGistPageGetOpaque(page)
#define GBUF_INNER_PARITY(x)
#define SpGistBlockIsFixed(blkno)
#define GBUF_REQ_LEAF(flags)
struct SpGistLeafTupleData SpGistLeafTupleData
IndexScanDesc spgbeginscan(Relation rel, int keysz, int orderbysz)
bool spgcanreturn(Relation index, int attno)
bool spggettuple(IndexScanDesc scan, ScanDirection dir)
void spgendscan(IndexScanDesc scan)
void spgrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys, ScanKey orderbys, int norderbys)
int64 spggetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
OffsetNumber SpGistPageAddNewItem(SpGistState *state, Page page, const void *item, Size size, OffsetNumber *startOffset, bool errorOK)
Datum * spgExtractNodeLabels(SpGistState *state, SpGistInnerTuple innerTuple)
void initSpGistState(SpGistState *state, Relation index)
void SpGistUpdateMetaPage(Relation index)
TupleDesc getSpGistTupleDesc(Relation index, SpGistTypeDesc *keyType)
Buffer SpGistNewBuffer(Relation index)
SpGistLeafTuple spgFormLeafTuple(SpGistState *state, const ItemPointerData *heapPtr, const Datum *datums, const bool *isnulls)
SpGistInnerTuple spgFormInnerTuple(SpGistState *state, bool hasPrefix, Datum prefix, int nNodes, SpGistNodeTuple *nodes)
static void memcpyInnerDatum(void *target, SpGistTypeDesc *att, Datum datum)
SpGistCache * spgGetCache(Relation index)
void spgDeformLeafTuple(SpGistLeafTuple tup, TupleDesc tupleDescriptor, Datum *datums, bool *isnulls, bool keyColumnIsNull)
SpGistDeadTuple spgFormDeadTuple(SpGistState *state, int tupstate, BlockNumber blkno, OffsetNumber offnum)
unsigned int SpGistGetInnerTypeSize(SpGistTypeDesc *att, Datum datum)
static Oid GetIndexInputType(Relation index, AttrNumber indexcol)
void SpGistInitBuffer(Buffer b, uint16 f)
Buffer SpGistGetBuffer(Relation index, int flags, int needSpace, bool *isNew)
bytea * spgoptions(Datum reloptions, bool validate)
static Buffer allocNewBuffer(Relation index, int flags)
bool spgproperty(Oid index_oid, int attno, IndexAMProperty prop, const char *propname, bool *res, bool *isnull)
void SpGistSetLastUsedPage(Relation index, Buffer buffer)
static void fillTypeDesc(SpGistTypeDesc *desc, Oid type)
Datum spghandler(PG_FUNCTION_ARGS)
Size SpGistGetLeafTupleSize(TupleDesc tupleDescriptor, const Datum *datums, const bool *isnulls)
void SpGistInitPage(Page page, uint16 f)
SpGistNodeTuple spgFormNodeTuple(SpGistState *state, Datum label, bool isnull)
void SpGistInitMetapage(Page page)
IndexBulkDeleteResult * spgbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, IndexBulkDeleteCallback callback, void *callback_state)
IndexBulkDeleteResult * spgvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
bool spgvalidate(Oid opclassoid)
void spgadjustmembers(Oid opfamilyoid, Oid opclassoid, List *operators, List *functions)
SpGistTypeDesc attPrefixType
SpGistTypeDesc attLeafType
SpGistLUPCache lastUsedPages
SpGistTypeDesc attLabelType
SpGistLastUsedPage cachedPage[SPGIST_CACHED_PAGES]
SpGistLUPCache lastUsedPages
CatCTup * members[FLEXIBLE_ARRAY_MEMBER]
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
#define ReleaseSysCacheList(x)
#define SearchSysCacheList1(cacheId, key1)
#define InvalidCompressionMethod
#define InvalidTransactionId
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
void populate_compact_attribute(TupleDesc tupdesc, int attnum)
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
static CompactAttribute * TupleDescCompactAttr(TupleDesc tupdesc, int i)
#define VACUUM_OPTION_PARALLEL_BULKDEL
#define VACUUM_OPTION_PARALLEL_COND_CLEANUP
static Size VARSIZE_ANY(const void *PTR)
TransactionId GetTopTransactionIdIfAny(void)