32#include "utils/fmgrprotos.h"
124 Assert(indexcol > 0 && indexcol <= index->rd_index->indnkeyatts);
125 opcintype =
index->rd_opcintype[indexcol - 1];
126 if (!IsPolymorphicType(opcintype))
128 heapcol =
index->rd_index->indkey.values[indexcol - 1];
138 if (
index->rd_indexprs)
139 indexprs =
index->rd_indexprs;
143 for (
int i = 1;
i <=
index->rd_index->indnkeyatts;
i++)
145 if (
index->rd_index->indkey.values[
i - 1] == 0)
148 if (indexpr_item == NULL)
149 elog(
ERROR,
"wrong number of index expressions");
152 indexpr_item =
lnext(indexprs, indexpr_item);
155 elog(
ERROR,
"wrong number of index expressions");
171 desc->
attlen = typtup->typlen;
187 if (
index->rd_amcache == NULL)
245 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
246 errmsg(
"compress method must be defined when leaf type is different from input type")));
263 if (
index->rd_rel->relkind != RELKIND_PARTITIONED_INDEX)
274 elog(
ERROR,
"index \"%s\" is not an SP-GiST index",
282 index->rd_amcache = cache;
323 att->atttypid = keyType->
type;
325 att->attlen = keyType->
attlen;
379 state->isBuild =
false;
485#define GET_LUP(c, f) (&(c)->lastUsedPages.cachedPage[((unsigned int) (f)) % SPGIST_CACHED_PAGES])
571 elog(
ERROR,
"desired SPGiST tuple size is too big");
640 if (freeSpace >= needSpace)
798 memcpy(target, &datum,
sizeof(
Datum));
814 const Datum *datums,
const bool *isnulls)
818 bool needs_null_mask =
false;
819 int natts = tupleDescriptor->
natts;
830 for (
int i = 0;
i < natts;
i++)
834 needs_null_mask =
true;
867 const Datum *datums,
const bool *isnulls)
874 bool needs_null_mask =
false;
875 int natts = tupleDescriptor->
natts;
888 for (
int i = 0;
i < natts;
i++)
892 needs_null_mask =
true;
907 size = hoff + data_size;
924 tp = (
char *) tup + hoff;
941 &tupmask, (
bits8 *) NULL);
959 unsigned short infomask = 0;
972 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
973 errmsg(
"index row requires %zu bytes, maximum size is %zu",
1002 unsigned int prefixSize;
1015 for (
i = 0;
i < nNodes;
i++)
1030 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1031 errmsg(
"SP-GiST inner tuple size %zu exceeds maximum %zu",
1034 errhint(
"Values larger than a buffer page cannot be indexed.")));
1043 elog(
ERROR,
"SPGiST inner tuple header field is too small");
1057 for (
i = 0;
i < nNodes;
i++)
1111 Datum *datums,
bool *isnulls,
bool keyColumnIsNull)
1117 if (keyColumnIsNull && tupleDescriptor->
natts == 1)
1135 tp = (
char *) tup +
SGLTHDRSZ(hasNullsMask);
1140 tp, bp, hasNullsMask);
1168 elog(
ERROR,
"some but not all node labels are null in SPGiST inner tuple");
1179 elog(
ERROR,
"some but not all node labels are null in SPGiST inner tuple");
1219 for (;
i <= maxoff;
i++)
1265 *startOffset = offnum + 1;
1268 elog(
PANIC,
"failed to add item of size %zu to SPGiST index page",
1280 elog(
ERROR,
"failed to add item of size %zu to SPGiST index page",
1295 bool *
res,
bool *isnull)
1347 if (amopform->amoppurpose == AMOP_ORDER &&
1348 (amopform->amoplefttype == opcintype ||
1349 amopform->amoprighttype == opcintype) &&
@ AMPROP_DISTANCE_ORDERABLE
bool opfamily_can_sort_type(Oid opfamilyoid, Oid datatypeoid)
#define InvalidBlockNumber
BlockNumber BufferGetBlockNumber(Buffer buffer)
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)
void LockBuffer(Buffer buffer, int mode)
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
#define BUFFER_LOCK_UNLOCK
#define BUFFER_LOCK_SHARE
static Page BufferGetPage(Buffer buffer)
static Size BufferGetPageSize(Buffer buffer)
void PageIndexTupleDelete(Page page, OffsetNumber offnum)
void PageInit(Page page, Size pageSize, Size specialSize)
Size PageGetExactFreeSpace(Page page)
PageHeaderData * PageHeader
static bool PageIsEmpty(Page page)
static Item PageGetItem(Page page, ItemId itemId)
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
static bool PageIsNew(Page page)
static OffsetNumber PageGetMaxOffsetNumber(Page page)
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
#define Assert(condition)
#define OidIsValid(objectId)
static void PGresult * res
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
#define PG_RETURN_POINTER(x)
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)
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)
#define IndexTupleHasNulls(itup)
#define IndexTupleSize(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)
static pg_noinline void Size size
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)
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)
SpGistInnerTuple spgFormInnerTuple(SpGistState *state, bool hasPrefix, Datum prefix, int nNodes, SpGistNodeTuple *nodes)
SpGistLeafTuple spgFormLeafTuple(SpGistState *state, ItemPointer heapPtr, const Datum *datums, const bool *isnulls)
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)
OffsetNumber SpGistPageAddNewItem(SpGistState *state, Page page, Item item, Size size, OffsetNumber *startOffset, bool errorOK)
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)
ambuildphasename_function ambuildphasename
ambuildempty_function ambuildempty
amvacuumcleanup_function amvacuumcleanup
amoptions_function amoptions
amestimateparallelscan_function amestimateparallelscan
amrestrpos_function amrestrpos
aminsert_function aminsert
amendscan_function amendscan
amparallelrescan_function amparallelrescan
amcostestimate_function amcostestimate
amadjustmembers_function amadjustmembers
amgettuple_function amgettuple
amcanreturn_function amcanreturn
amgetbitmap_function amgetbitmap
amproperty_function amproperty
ambulkdelete_function ambulkdelete
amvalidate_function amvalidate
ammarkpos_function ammarkpos
bool amusemaintenanceworkmem
ambeginscan_function ambeginscan
amrescan_function amrescan
aminitparallelscan_function aminitparallelscan
uint8 amparallelvacuumoptions
aminsertcleanup_function aminsertcleanup
amgettreeheight_function amgettreeheight
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
TransactionId GetTopTransactionIdIfAny(void)