67 elog(
ERROR,
"failed to find requested node %d in SPGiST inner tuple",
89 else if (offset > tuple->
nNodes)
90 elog(
ERROR,
"invalid offset for adding node to SPGiST inner tuple");
133 int firststate,
int reststate,
157 firstItem = itemnos[0];
164 tupstate = (itemno == firstItem) ? firststate : reststate;
165 if (tuple == NULL || tuple->
tupstate != tupstate)
168 if (
PageAddItem(page, tuple, tuple->
size, itemno,
false,
false) != itemno)
169 elog(
ERROR,
"failed to add item of size %u to SPGiST index page",
224 leafTuple, leafTuple->
size,
257 leafTuple, leafTuple->
size,
276 leafTuple, leafTuple->
size,
278 elog(
ERROR,
"failed to add item of size %u to SPGiST index page",
398 bool replaceDead =
false;
430 toDelete[nDelete] =
i;
440 toDelete[nDelete] =
i;
457 leafdata = leafptr =
palloc(size);
465 for (
i = 0;
i < nDelete;
i++)
482 toInsert[nInsert] = r;
486 memcpy(leafptr, it, it->
size);
494 toInsert[nInsert] = r;
496 memcpy(leafptr, newLeafTuple, newLeafTuple->
size);
497 leafptr += newLeafTuple->
size;
614 for (
i = 1;
i < limit;
i++)
676 int level,
bool isNulls,
bool isNew)
678 bool insertedNew =
false;
691 uint8 *leafPageSelect;
702 int currentFreeSpace;
755 oldLeafs[nToInsert] = it;
757 toDelete[nToDelete] =
i;
781 oldLeafs[nToInsert] = it;
783 toDelete[nToDelete] =
i;
794 toDelete[nToDelete] =
i;
814 oldLeafs[in.
nTuples] = newLeafTuple;
817 memset(&out, 0,
sizeof(out));
826 index->rd_indcollation[0],
836 if (
state->leafTupDesc->natts > 1)
869 if (
state->leafTupDesc->natts > 1)
949 for (
i = 0;
i < maxToInclude;
i++)
952 if (n < 0 || n >= out.
nNodes)
953 elog(
ERROR,
"inconsistent result of SPGiST picksplit function");
973 newInnerBuffer = parent->
buffer;
1011 currentFreeSpace = 0;
1015 if (totalLeafSizes <= currentFreeSpace)
1025 for (
i = 0;
i < nToInsert;
i++)
1026 leafPageSelect[
i] = 0;
1042 uint8 *nodePageSelect;
1059 curspace = currentFreeSpace;
1063 if (leafSizes[
i] <= curspace)
1065 nodePageSelect[
i] = 0;
1066 curspace -= leafSizes[
i];
1070 nodePageSelect[
i] = 1;
1071 newspace -= leafSizes[
i];
1074 if (curspace >= 0 && newspace >= 0)
1083 else if (includeNew)
1088 leafSizes[nodeOfNewTuple] -=
1092 curspace = currentFreeSpace;
1096 if (leafSizes[
i] <= curspace)
1098 nodePageSelect[
i] = 0;
1099 curspace -= leafSizes[
i];
1103 nodePageSelect[
i] = 1;
1104 newspace -= leafSizes[
i];
1107 if (curspace < 0 || newspace < 0)
1108 elog(
ERROR,
"failed to divide leaf tuple groups across pages");
1113 elog(
ERROR,
"failed to divide leaf tuple groups across pages");
1116 for (
i = 0;
i < nToInsert;
i++)
1119 leafPageSelect[
i] = nodePageSelect[n];
1129 leafdata = leafptr = (
char *)
palloc(totalLeafSizes);
1146 if (
state->isBuild &&
1163 if (!
state->isBuild)
1172 redirectTuplePos = toDelete[0];
1174 toDelete, nToDelete,
1187 toDelete, nToDelete,
1201 for (
i = 0;
i < nToInsert;
i++)
1209 leafBuffer = leafPageSelect[
i] ? newLeafBuffer : current->
buffer;
1226 &startOffsets[leafPageSelect[
i]],
1228 toInsert[
i] = newoffset;
1234 memcpy(leafptr, newLeafs[
i], newLeafs[
i]->size);
1235 leafptr += newLeafs[
i]->
size;
1249 saveCurrent = *current;
1267 innerTuple, innerTuple->
size,
1296 current->
buffer = newInnerBuffer;
1301 innerTuple, innerTuple->
size,
1342 elog(
ERROR,
"failed to add item of size %u to SPGiST index page",
1475 parent->
node = nodeN;
1485 elog(
ERROR,
"failed to find requested node %d in SPGiST inner tuple",
1502 current->
page = NULL;
1512 int nodeN,
Datum nodeLabel)
1521 newInnerTuple =
addNode(
state, innerTuple, nodeLabel, nodeN);
1537 newInnerTuple->
size - innerTuple->
size)
1546 newInnerTuple, newInnerTuple->
size,
1548 elog(
ERROR,
"failed to add item of size %u to SPGiST index page",
1549 newInnerTuple->
size);
1584 elog(
ERROR,
"cannot enlarge root tuple any more");
1587 saveCurrent = *current;
1612 elog(
ERROR,
"SPGiST new buffer shouldn't be same as old buffer");
1630 newInnerTuple, newInnerTuple->
size,
1655 false,
false) != saveCurrent.
offnum)
1656 elog(
ERROR,
"failed to add item of size %u to SPGiST index page",
1731 elog(
ERROR,
"invalid number of prefix nodes: %d",
1736 elog(
ERROR,
"invalid child node number: %d",
1764 if (prefixTuple->
size > innerTuple->
size)
1765 elog(
ERROR,
"SPGiST inner-tuple split must not produce longer prefix");
1781 innerTuple->
nNodes, nodes);
1817 prefixTuple, prefixTuple->
size,
1818 current->
offnum,
false,
false);
1820 elog(
ERROR,
"failed to add item of size %u to SPGiST index page",
1828 postfixBlkno = current->
blkno;
1831 postfixTuple, postfixTuple->
size,
1840 postfixTuple, postfixTuple->
size,
1854 postfixBlkno, postfixOffset);
1858 postfixBlkno, postfixOffset);
1920 int numNoProgressCycles = 0;
1958 if (
state->attType.attlen == -1)
1976 leafDatums[
i] = datums[
i];
1979 leafDatums[
i] = (
Datum) 0;
1994 (isnull || !
state->config.longValuesOK))
1996 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1997 errmsg(
"index row size %zu exceeds maximum %zu for index \"%s\"",
2001 errhint(
"Values larger than a buffer page cannot be indexed.")));
2002 bestLeafSize = leafSize;
2007 current.
page = NULL;
2100 elog(
ERROR,
"SPGiST index page %u has wrong nulls flag",
2115 ¤t, &parent, isnull, isNew);
2118 else if ((sizeToSplit =
2136 leafTuple, level, isnull, isNew))
2146 goto process_inner_tuple;
2165 process_inner_tuple:
2184 memset(&out, 0,
sizeof(out));
2190 index->rd_indcollation[0],
2208 elog(
ERROR,
"cannot add a node to an allTheSame inner tuple");
2212 0, innerTuple->
nNodes - 1);
2229 leafDatums, isnulls);
2260 if (
state->config.longValuesOK && !isnull)
2262 if (leafSize < bestLeafSize)
2265 bestLeafSize = leafSize;
2266 numNoProgressCycles = 0;
2268 else if (++numNoProgressCycles < 10)
2273 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
2274 errmsg(
"index row size %zu exceeds maximum %zu for index \"%s\"",
2278 errhint(
"Values larger than a buffer page cannot be indexed.")));
2291 elog(
ERROR,
"cannot add a node to an inner tuple without node labels");
2302 goto process_inner_tuple;
2310 goto process_inner_tuple;
2313 elog(
ERROR,
"unrecognized SPGiST choose result: %d",
#define InvalidBlockNumber
BlockNumber BufferGetBlockNumber(Buffer buffer)
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)
static Page BufferGetPage(Buffer buffer)
#define BUFFER_LOCK_EXCLUSIVE
static bool BufferIsValid(Buffer bufnum)
void PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
void PageIndexTupleDelete(Page page, OffsetNumber offnum)
Size PageGetExactFreeSpace(const PageData *page)
static void * PageGetItem(const PageData *page, const ItemIdData *itemId)
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
static void PageSetLSN(Page page, XLogRecPtr lsn)
#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,...)
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
#define PG_DETOAST_DATUM(datum)
Assert(PointerIsAligned(start, uint64))
FmgrInfo * index_getprocinfo(Relation irel, AttrNumber attnum, uint16 procnum)
RegProcedure index_getprocid(Relation irel, AttrNumber attnum, uint16 procnum)
static int pg_cmp_u16(uint16 a, uint16 b)
if(TABLE==NULL||TABLE_index==NULL)
struct ItemIdData ItemIdData
static void ItemPointerSet(ItemPointerData *pointer, BlockNumber blockNumber, OffsetNumber offNum)
static OffsetNumber ItemPointerGetOffsetNumber(const ItemPointerData *pointer)
static BlockNumber ItemPointerGetBlockNumber(const ItemPointerData *pointer)
static bool ItemPointerIsValid(const ItemPointerData *pointer)
#define MaxIndexTuplesPerPage
void pfree(void *pointer)
void * palloc0(Size size)
#define INTERRUPTS_CAN_BE_PROCESSED()
#define START_CRIT_SECTION()
#define CHECK_FOR_INTERRUPTS()
#define INTERRUPTS_PENDING_CONDITION()
#define END_CRIT_SECTION()
#define InvalidOffsetNumber
#define FirstOffsetNumber
uint64 pg_prng_uint64_range(pg_prng_state *state, uint64 rmin, uint64 rmax)
pg_prng_state pg_global_prng_state
#define qsort(a, b, c, d)
static Datum PointerGetDatum(const void *X)
#define RelationGetRelationName(relation)
#define RelationNeedsWAL(relation)
static void spgAddNodeAction(Relation index, SpGistState *state, SpGistInnerTuple innerTuple, SPPageDesc *current, SPPageDesc *parent, int nodeN, Datum nodeLabel)
static void setRedirectionTuple(SPPageDesc *current, OffsetNumber position, BlockNumber blkno, OffsetNumber offnum)
static bool checkAllTheSame(spgPickSplitIn *in, spgPickSplitOut *out, bool tooBig, bool *includeNew)
static void spgSplitNodeAction(Relation index, SpGistState *state, SpGistInnerTuple innerTuple, SPPageDesc *current, spgChooseOut *out)
static SpGistInnerTuple addNode(SpGistState *state, SpGistInnerTuple tuple, Datum label, int offset)
void spgPageIndexMultiDelete(SpGistState *state, Page page, OffsetNumber *itemnos, int nitems, int firststate, int reststate, BlockNumber blkno, OffsetNumber offnum)
bool spgdoinsert(Relation index, SpGistState *state, const ItemPointerData *heapPtr, const Datum *datums, const bool *isnulls)
static void spgMatchNodeAction(Relation index, SpGistState *state, SpGistInnerTuple innerTuple, SPPageDesc *current, SPPageDesc *parent, int nodeN)
static bool doPickSplit(Relation index, SpGistState *state, SPPageDesc *current, SPPageDesc *parent, SpGistLeafTuple newLeafTuple, int level, bool isNulls, bool isNew)
void spgUpdateNodeLink(SpGistInnerTuple tup, int nodeN, BlockNumber blkno, OffsetNumber offset)
static void moveLeafs(Relation index, SpGistState *state, SPPageDesc *current, SPPageDesc *parent, SpGistLeafTuple newLeafTuple, bool isNulls)
static void saveNodeLink(Relation index, SPPageDesc *parent, BlockNumber blkno, OffsetNumber offnum)
struct SPPageDesc SPPageDesc
static int checkSplitConditions(Relation index, SpGistState *state, SPPageDesc *current, int *nToSplit)
static void addLeafTuple(Relation index, SpGistState *state, SpGistLeafTuple leafTuple, SPPageDesc *current, SPPageDesc *parent, bool isNulls, bool isNew)
static int cmpOffsetNumbers(const void *a, const void *b)
#define SPGIST_COMPRESS_PROC
#define SPGIST_CHOOSE_PROC
#define SPGIST_PICKSPLIT_PROC
#define SPGIST_NULL_BLKNO
SpGistDeadTupleData * SpGistDeadTuple
SpGistInnerTupleData * SpGistInnerTuple
#define SpGistPageStoresNulls(page)
#define SGLT_GET_NEXTOFFSET(spgLeafTuple)
#define SPGIST_PLACEHOLDER
#define SGITITERATE(x, i, nt)
#define spgFirstIncludeColumn
#define SpGistPageIsLeaf(page)
#define SPGIST_METAPAGE_BLKNO
#define SGLT_SET_NEXTOFFSET(spgLeafTuple, offsetNumber)
#define SpGistBlockIsRoot(blkno)
struct SpGistLeafTupleData * SpGistLeafTuple
#define STORE_STATE(s, d)
#define SPGIST_PAGE_CAPACITY
#define SpGistPageGetOpaque(page)
#define GBUF_INNER_PARITY(x)
#define SPGIST_ROOT_BLKNO
#define SpGistPageGetFreeSpace(p, n)
OffsetNumber SpGistPageAddNewItem(SpGistState *state, Page page, const void *item, Size size, OffsetNumber *startOffset, bool errorOK)
Datum * spgExtractNodeLabels(SpGistState *state, SpGistInnerTuple innerTuple)
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)
void spgDeformLeafTuple(SpGistLeafTuple tup, TupleDesc tupleDescriptor, Datum *datums, bool *isnulls, bool keyColumnIsNull)
SpGistDeadTuple spgFormDeadTuple(SpGistState *state, int tupstate, BlockNumber blkno, OffsetNumber offnum)
void SpGistInitBuffer(Buffer b, uint16 f)
Buffer SpGistGetBuffer(Relation index, int flags, int needSpace, bool *isNew)
void SpGistSetLastUsedPage(Relation index, Buffer buffer)
Size SpGistGetLeafTupleSize(TupleDesc tupleDescriptor, const Datum *datums, const bool *isnulls)
SpGistNodeTuple spgFormNodeTuple(SpGistState *state, Datum label, bool isnull)
#define XLOG_SPGIST_SPLIT_TUPLE
#define SizeOfSpgxlogPickSplit
#define SizeOfSpgxlogMoveLeafs
#define XLOG_SPGIST_ADD_NODE
#define XLOG_SPGIST_ADD_LEAF
#define XLOG_SPGIST_MOVE_LEAFS
#define XLOG_SPGIST_PICKSPLIT
spgChooseResultType resultType
struct spgChooseOut::@53::@54 matchNode
struct spgChooseOut::@53::@56 splitTuple
union spgChooseOut::@53 result
struct spgChooseOut::@53::@55 addNode
OffsetNumber offnumHeadLeaf
OffsetNumber offnumParent
OffsetNumber offnumParent
OffsetNumber offnumParent
OffsetNumber offnumParent
OffsetNumber offnumPostfix
OffsetNumber offnumPrefix
static CompactAttribute * TupleDescCompactAttr(TupleDesc tupdesc, int i)
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
void XLogRegisterData(const void *data, uint32 len)
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
void XLogBeginInsert(void)