32 #include "utils/fmgrprotos.h"
123 Assert(indexcol > 0 && indexcol <= index->rd_index->indnkeyatts);
124 opcintype =
index->rd_opcintype[indexcol - 1];
125 if (!IsPolymorphicType(opcintype))
127 heapcol =
index->rd_index->indkey.values[indexcol - 1];
137 if (
index->rd_indexprs)
138 indexprs =
index->rd_indexprs;
142 for (
int i = 1;
i <=
index->rd_index->indnkeyatts;
i++)
144 if (
index->rd_index->indkey.values[
i - 1] == 0)
147 if (indexpr_item == NULL)
148 elog(
ERROR,
"wrong number of index expressions");
151 indexpr_item =
lnext(indexprs, indexpr_item);
154 elog(
ERROR,
"wrong number of index expressions");
170 desc->
attlen = typtup->typlen;
186 if (
index->rd_amcache == NULL)
244 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
245 errmsg(
"compress method must be defined when leaf type is different from input type")));
262 if (
index->rd_rel->relkind != RELKIND_PARTITIONED_INDEX)
273 elog(
ERROR,
"index \"%s\" is not an SP-GiST index",
281 index->rd_amcache = (
void *) cache;
322 att->atttypid = keyType->
type;
324 att->attlen = keyType->
attlen;
376 state->isBuild =
false;
482 #define GET_LUP(c, f) (&(c)->lastUsedPages.cachedPage[((unsigned int) (f)) % SPGIST_CACHED_PAGES])
568 elog(
ERROR,
"desired SPGiST tuple size is too big");
637 if (freeSpace >= needSpace)
795 memcpy(target, &datum,
sizeof(
Datum));
811 const Datum *datums,
const bool *isnulls)
815 bool needs_null_mask =
false;
816 int natts = tupleDescriptor->
natts;
827 for (
int i = 0;
i < natts;
i++)
831 needs_null_mask =
true;
864 const Datum *datums,
const bool *isnulls)
871 bool needs_null_mask =
false;
872 int natts = tupleDescriptor->
natts;
885 for (
int i = 0;
i < natts;
i++)
889 needs_null_mask =
true;
904 size = hoff + data_size;
921 tp = (
char *) tup + hoff;
938 &tupmask, (
bits8 *) NULL);
956 unsigned short infomask = 0;
969 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
970 errmsg(
"index row requires %zu bytes, maximum size is %zu",
999 unsigned int prefixSize;
1012 for (
i = 0;
i < nNodes;
i++)
1027 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1028 errmsg(
"SP-GiST inner tuple size %zu exceeds maximum %zu",
1031 errhint(
"Values larger than a buffer page cannot be indexed.")));
1040 elog(
ERROR,
"SPGiST inner tuple header field is too small");
1054 for (
i = 0;
i < nNodes;
i++)
1108 Datum *datums,
bool *isnulls,
bool keyColumnIsNull)
1114 if (keyColumnIsNull && tupleDescriptor->
natts == 1)
1132 tp = (
char *) tup +
SGLTHDRSZ(hasNullsMask);
1137 tp, bp, hasNullsMask);
1165 elog(
ERROR,
"some but not all node labels are null in SPGiST inner tuple");
1176 elog(
ERROR,
"some but not all node labels are null in SPGiST inner tuple");
1216 for (;
i <= maxoff;
i++)
1262 *startOffset = offnum + 1;
1265 elog(
PANIC,
"failed to add item of size %zu to SPGiST index page",
1277 elog(
ERROR,
"failed to add item of size %zu to SPGiST index page",
1292 bool *
res,
bool *isnull)
1344 if (amopform->amoppurpose == AMOP_ORDER &&
1345 (amopform->amoplefttype == opcintype ||
1346 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 * palloc0(Size size)
void * MemoryContextAllocZero(MemoryContext context, 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
bool spginsert(Relation index, Datum *values, bool *isnull, ItemPointer ht_ctid, Relation heapRel, IndexUniqueCheck checkUnique, bool indexUnchanged, IndexInfo *indexInfo)
void spgbuildempty(Relation index)
IndexBuildResult * spgbuild(Relation heap, Relation index, IndexInfo *indexInfo)
#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)
bytea * spgoptions(Datum reloptions, bool validate)
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)
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)
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)
SpGistCache * spgGetCache(Relation index)
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 * spgvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
IndexBulkDeleteResult * spgbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, IndexBulkDeleteCallback callback, void *callback_state)
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
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)
#define TupleDescAttr(tupdesc, i)
#define VACUUM_OPTION_PARALLEL_BULKDEL
#define VACUUM_OPTION_PARALLEL_COND_CLEANUP
TransactionId GetTopTransactionIdIfAny(void)