29 #define BTREE_FASTPATH_MIN_LEVEL 2 52 bool split_only_page);
58 BTStack stack,
bool isroot,
bool isonly);
64 bool simpleonly,
bool checkingunique,
65 bool uniquedup,
bool indexUnchanged);
73 static inline int _bt_blk_cmp(
const void *arg1,
const void *arg2);
103 bool is_unique =
false;
130 checkingunique =
false;
150 insertstate.
itup = itup;
208 &is_unique, &speculativeToken);
221 if (speculativeToken)
256 indexUnchanged, stack, heapRel);
258 itup, insertstate.
itemsz, newitemoff,
420 bool inposting =
false;
421 bool prevalldead =
true;
466 if (offset <= maxoff)
505 bool all_dead =
false;
523 htid = curitup->
t_tid;
584 SnapshotDirty.
xmin : SnapshotDirty.
xmax;
664 (
errcode(ERRCODE_UNIQUE_VIOLATION),
665 errmsg(
"duplicate key value violates unique constraint \"%s\"",
667 key_desc ?
errdetail(
"Key %s already exists.",
673 else if (all_dead && (!inposting ||
699 if (!all_dead && inposting)
710 else if (offset < maxoff)
739 elog(
ERROR,
"fell off the end of index \"%s\"",
758 (
errcode(ERRCODE_INTERNAL_ERROR),
759 errmsg(
"failed to re-find tuple within index \"%s\"",
761 errhint(
"This may be because of a non-immutable index expression."),
843 bool uniquedup = indexUnchanged;
905 checkingunique, uniquedup,
948 false,
false,
false);
999 false,
false,
false);
1061 elog(
ERROR,
"fell off the end of index \"%s\"",
1068 insertstate->
buf = rbuf;
1112 bool split_only_page)
1156 if (postingoff != 0)
1192 Assert(!split_only_page);
1195 rbuf =
_bt_split(rel, itup_key, buf, cbuf, newitemoff, itemsz, itup,
1196 origitup, nposting, postingoff);
1255 if (postingoff != 0)
1260 elog(
PANIC,
"failed to add new item to block %u in index \"%s\"",
1298 xlrec.
offnum = newitemoff;
1303 if (isleaf && postingoff == 0)
1308 else if (postingoff != 0)
1347 if (postingoff == 0)
1362 upostingoff = postingoff;
1392 if (isrightmost && isleaf && !isroot)
1411 if (postingoff != 0)
1523 newitem, &newitemonleft);
1569 if (postingoff != 0)
1573 &newitem->
t_tid) < 0);
1598 if (!newitemonleft && newitemoff == firstrightoff)
1602 firstright = newitem;
1610 if (firstrightoff == origpagepostingoff)
1611 firstright = nposting;
1619 if (newitemonleft && newitemoff == firstrightoff)
1633 if (lastleftoff == origpagepostingoff)
1634 lastleft = nposting;
1637 lefthighkey =
_bt_truncate(rel, lastleft, firstright, itup_key);
1668 lefthighkey = firstright;
1680 if (
PageAddItem(leftpage, (
Item) lefthighkey, itemsz, afterleftoff,
false,
1682 elog(
ERROR,
"failed to add high key to the left sibling" 1683 " while splitting block %u of index \"%s\"",
1747 if (
PageAddItem(rightpage, (
Item) righthighkey, itemsz, afterrightoff,
1751 elog(
ERROR,
"failed to add high key to the right sibling" 1752 " while splitting block %u of index \"%s\"",
1764 minusinfoff = afterrightoff;
1782 if (i == origpagepostingoff)
1786 dataitem = nposting;
1790 else if (i == newitemoff)
1794 Assert(newitemoff <= firstrightoff);
1795 if (!
_bt_pgaddtup(leftpage, newitemsz, newitem, afterleftoff,
1799 elog(
ERROR,
"failed to add new item to the left sibling" 1800 " while splitting block %u of index \"%s\"",
1807 Assert(newitemoff >= firstrightoff);
1808 if (!
_bt_pgaddtup(rightpage, newitemsz, newitem, afterrightoff,
1809 afterrightoff == minusinfoff))
1812 elog(
ERROR,
"failed to add new item to the right sibling" 1813 " while splitting block %u of index \"%s\"",
1821 if (i < firstrightoff)
1823 if (!
_bt_pgaddtup(leftpage, itemsz, dataitem, afterleftoff,
false))
1826 elog(
ERROR,
"failed to add old item to the left sibling" 1827 " while splitting block %u of index \"%s\"",
1834 if (!
_bt_pgaddtup(rightpage, itemsz, dataitem, afterrightoff,
1835 afterrightoff == minusinfoff))
1838 elog(
ERROR,
"failed to add old item to the right sibling" 1839 " while splitting block %u of index \"%s\"",
1847 if (i <= newitemoff)
1854 Assert(!newitemonleft && newitemoff == maxoff + 1);
1855 if (!
_bt_pgaddtup(rightpage, newitemsz, newitem, afterrightoff,
1856 afterrightoff == minusinfoff))
1859 elog(
ERROR,
"failed to add new item to the right sibling" 1860 " while splitting block %u of index \"%s\"",
1876 if (sopaque->
btpo_prev != origpagenumber)
1880 (
errcode(ERRCODE_INDEX_CORRUPTED),
1882 "block %u links to %u instead of expected %u in index \"%s\"",
1958 if (postingoff != 0 && origpagepostingoff < firstrightoff)
1999 if (newitemonleft && xlrec.postingoff == 0)
2001 else if (xlrec.postingoff != 0)
2004 Assert(newitemonleft || firstrightoff == newitemoff);
2030 (
char *) rightpage + ((
PageHeader) rightpage)->pd_upper,
2190 (
errcode(ERRCODE_INDEX_CORRUPTED),
2191 errmsg_internal(
"failed to re-find parent key in index \"%s\" for split pages %u/%u",
2254 elog(
DEBUG1,
"finishing incomplete split of %u/%u",
2347 for (offnum = start;
2458 left_item->
t_info = left_item_sz;
2504 elog(
PANIC,
"failed to add leftkey to new root page" 2505 " while splitting block %u of index \"%s\"",
2516 elog(
PANIC,
"failed to add rightkey to new root page" 2517 " while splitting block %u of index \"%s\"",
2547 md.
root = rootblknum;
2562 (
char *) rootpage + ((
PageHeader) rootpage)->pd_upper,
2607 bool newfirstdataitem)
2611 if (newfirstdataitem)
2658 bool simpleonly,
bool checkingunique,
2659 bool uniquedup,
bool indexUnchanged)
2673 Assert(!simpleonly || (!checkingunique && !uniquedup && !indexUnchanged));
2684 for (offnum = minoff;
2691 deletable[ndeletable++] = offnum;
2697 insertstate->
itup, minoff, maxoff);
2721 if (simpleonly || (checkingunique && !uniquedup))
2747 if ((indexUnchanged || uniquedup) &&
2754 insertstate->
itemsz, checkingunique);
2796 deadblocks =
_bt_deadblocks(page, deletable, ndeletable, newitem,
2806 for (offnum = minoff;
2820 match = bsearch(&tidblock, deadblocks, ndeadblocks,
2846 for (
int p = 0; p < nitem; p++)
2851 match = bsearch(&tidblock, deadblocks, ndeadblocks,
2864 odeltid->
tid = *tid;
2922 spacentids = ndeletable + 1;
2934 for (
int i = 0;
i < ndeletable;
i++)
2943 if (ntids + 1 > spacentids)
2956 if (ntids + nposting > spacentids)
2958 spacentids =
Max(spacentids * 2, ntids + nposting);
2963 for (
int j = 0; j < nposting; j++)
static void _bt_insertonpg(Relation rel, BTScanInsert itup_key, Buffer buf, Buffer cbuf, BTStack stack, IndexTuple itup, Size itemsz, OffsetNumber newitemoff, int postingoff, bool split_only_page)
int32 ItemPointerCompare(ItemPointer arg1, ItemPointer arg2)
void XLogRegisterBufData(uint8 block_id, char *data, int len)
void _bt_freestack(BTStack stack)
BTCycleId _bt_vacuum_cycleid(Relation rel)
#define InitDirtySnapshot(snapshotdata)
int errhint(const char *fmt,...)
void _bt_delitems_delete_check(Relation rel, Buffer buf, Relation heapRel, TM_IndexDeleteOp *delstate)
void PageRestoreTempPage(Page tempPage, Page oldPage)
void _bt_upgrademetapage(Page page)
static bool BTreeTupleIsPivot(IndexTuple itup)
int _bt_getrootheight(Relation rel)
Buffer _bt_relandgetbuf(Relation rel, Buffer obuf, BlockNumber blkno, int access)
void MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
#define RelationGetDescr(relation)
#define ItemIdMarkDead(itemId)
BTScanInsert _bt_mkscankey(Relation rel, IndexTuple itup)
Buffer _bt_getbuf(Relation rel, BlockNumber blkno, int access)
void MarkBufferDirty(Buffer buffer)
#define BTGetDeduplicateItems(relation)
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
static void _bt_insert_parent(Relation rel, Buffer buf, Buffer rbuf, BTStack stack, bool isroot, bool isonly)
static void _bt_simpledel_pass(Relation rel, Buffer buffer, Relation heapRel, OffsetNumber *deletable, int ndeletable, IndexTuple newitem, OffsetNumber minoff, OffsetNumber maxoff)
#define P_FIRSTDATAKEY(opaque)
#define END_CRIT_SECTION()
static BlockNumber BTreeTupleGetDownLink(IndexTuple pivot)
#define XLOG_BTREE_INSERT_META
#define P_HAS_GARBAGE(opaque)
#define START_CRIT_SECTION()
int errcode(int sqlerrcode)
#define BTP_INCOMPLETE_SPLIT
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
static void _bt_stepright(Relation rel, BTInsertState insertstate, BTStack stack)
void ReleaseBuffer(Buffer buffer)
static Buffer _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
#define P_INCOMPLETE_SPLIT(opaque)
#define MaxTIDsPerBTreePage
#define ItemIdIsDead(itemId)
#define BTreeTupleGetNAtts(itup, rel)
Buffer _bt_get_endpoint(Relation rel, uint32 level, bool rightmost, Snapshot snapshot)
IndexTuple _bt_swap_posting(IndexTuple newitem, IndexTuple oposting, int postingoff)
#define PageGetMaxOffsetNumber(page)
#define RelationGetTargetBlock(relation)
BTPageOpaqueData * BTPageOpaque
Size PageGetFreeSpace(Page page)
static Buffer _bt_split(Relation rel, BTScanInsert itup_key, Buffer buf, Buffer cbuf, OffsetNumber newitemoff, Size newitemsz, IndexTuple newitem, IndexTuple orignewitem, IndexTuple nposting, uint16 postingoff)
static int _bt_blk_cmp(const void *arg1, const void *arg2)
static void BTreeTupleSetNAtts(IndexTuple itup, uint16 nkeyatts, bool heaptid)
IndexTuple _bt_truncate(Relation rel, IndexTuple lastleft, IndexTuple firstright, BTScanInsert itup_key)
int errtableconstraint(Relation rel, const char *conname)
#define XLOG_BTREE_NEWROOT
#define ItemIdGetLength(itemId)
void pfree(void *pointer)
void _bt_finish_split(Relation rel, Buffer lbuf, BTStack stack)
void _bt_checkpage(Relation rel, Buffer buf)
#define XLOG_BTREE_INSERT_LEAF
void SpeculativeInsertionWait(TransactionId xid, uint32 token)
IndexTuple CopyIndexTuple(IndexTuple source)
OffsetNumber _bt_binsrch_insert(Relation rel, BTInsertState insertstate)
IndexTupleData * IndexTuple
int errdetail(const char *fmt,...)
#define IndexRelationGetNumberOfAttributes(relation)
#define InvalidTransactionId
#define RelationGetRelationName(relation)
#define P_LEFTMOST(opaque)
void index_deform_tuple(IndexTuple tup, TupleDesc tupleDescriptor, Datum *values, bool *isnull)
static void BTreeTupleSetDownLink(IndexTuple pivot, BlockNumber blkno)
#define IndexRelationGetNumberOfKeyAttributes(relation)
#define BTREE_NOVAC_VERSION
int32 _bt_compare(Relation rel, BTScanInsert key, Page page, OffsetNumber offnum)
static BTStack _bt_search_insert(Relation rel, BTInsertState insertstate)
#define BufferGetPage(buffer)
static OffsetNumber _bt_findinsertloc(Relation rel, BTInsertState insertstate, bool checkingunique, bool indexUnchanged, BTStack stack, Relation heapRel)
bool table_index_fetch_tuple_check(Relation rel, ItemPointer tid, Snapshot snapshot, bool *all_dead)
uint32 btm_last_cleanup_num_delpages
#define BTREE_FASTPATH_MIN_LEVEL
#define SizeOfBtreeNewroot
OffsetNumber _bt_findsplitloc(Relation rel, Page origpage, OffsetNumber newitemoff, Size newitemsz, IndexTuple newitem, bool *newitemonleft)
#define PageGetItemId(page, offsetNumber)
void XLogRegisterData(char *data, int len)
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Page PageGetTempPage(Page page)
struct IndexTupleData IndexTupleData
#define BufferGetPageSize(buffer)
bool _bt_doinsert(Relation rel, IndexTuple itup, IndexUniqueCheck checkUnique, bool indexUnchanged, Relation heapRel)
void CheckForSerializableConflictIn(Relation relation, ItemPointer tid, BlockNumber blkno)
#define InvalidOffsetNumber
void _bt_relbuf(Relation rel, Buffer buf)
#define XLOG_BTREE_SPLIT_R
void _bt_dedup_pass(Relation rel, Buffer buf, Relation heapRel, IndexTuple newitem, Size newitemsz, bool checkingunique)
#define ereport(elevel,...)
#define BlockNumberIsValid(blockNumber)
static ItemPointer BTreeTupleGetPostingN(IndexTuple posting, int n)
static bool BTreeTupleIsPosting(IndexTuple itup)
int errmsg_internal(const char *fmt,...)
bool _bt_bottomupdel_pass(Relation rel, Buffer buf, Relation heapRel, Size newitemsz)
static void _bt_delete_or_dedup_one_page(Relation rel, Relation heapRel, BTInsertState insertstate, bool simpleonly, bool checkingunique, bool uniquedup, bool indexUnchanged)
void XactLockTableWait(TransactionId xid, Relation rel, ItemPointer ctid, XLTW_Oper oper)
#define Assert(condition)
static BlockNumber * _bt_deadblocks(Page page, OffsetNumber *deletable, int ndeletable, IndexTuple newitem, int *nblocks)
#define XLOG_BTREE_INSERT_POST
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
#define RelationSetTargetBlock(relation, targblock)
#define OffsetNumberNext(offsetNumber)
#define PageGetSpecialPointer(page)
#define InvalidBlockNumber
#define OffsetNumberPrev(offsetNumber)
float8 btm_last_cleanup_num_heap_tuples
static size_t qunique(void *array, size_t elements, size_t width, int(*compare)(const void *, const void *))
#define BufferIsValid(bufnum)
struct BTStackData * bts_parent
#define RelationNeedsWAL(relation)
void * repalloc(void *pointer, Size size)
#define XLOG_BTREE_INSERT_UPPER
void _bt_check_third_page(Relation rel, Relation heap, bool needheaptidspace, Page page, IndexTuple newtup)
#define BTMaxItemSize(page)
static Datum values[MAXATTR]
BlockNumber BufferGetBlockNumber(Buffer buffer)
static TransactionId _bt_check_unique(Relation rel, BTInsertState insertstate, Relation heapRel, IndexUniqueCheck checkUnique, bool *is_unique, uint32 *speculativeToken)
#define MaxIndexTuplesPerPage
int errmsg(const char *fmt,...)
void _bt_pageinit(Page page, Size size)
static bool _bt_pgaddtup(Page page, Size itemsize, IndexTuple itup, OffsetNumber itup_off, bool newfirstdataitem)
#define XLOG_BTREE_SPLIT_L
static uint16 BTreeTupleGetNPosting(IndexTuple posting)
bool _bt_conditionallockbuf(Relation rel, Buffer buf)
char * BuildIndexValueDescription(Relation indexRelation, Datum *values, bool *isnull)
#define ItemPointerGetBlockNumber(pointer)
#define qsort(a, b, c, d)
#define TransactionIdIsValid(xid)
void XLogBeginInsert(void)
OffsetNumber firstrightoff
#define PageSetLSN(page, lsn)
#define P_RIGHTMOST(opaque)
#define SizeOfBtreeInsert
void PredicateLockPageSplit(Relation relation, BlockNumber oldblkno, BlockNumber newblkno)
BTStack _bt_search(Relation rel, BTScanInsert key, Buffer *bufP, int access, Snapshot snapshot)
Buffer _bt_getstackbuf(Relation rel, BTStack stack, BlockNumber child)
#define PageGetItem(page, itemId)
#define IndexTupleSize(itup)