32#define BTREE_FASTPATH_MIN_LEVEL 2
57 bool split_only_page);
69 bool simpleonly,
bool checkingunique,
70 bool uniquedup,
bool indexUnchanged);
78static inline int _bt_blk_cmp(
const void *arg1,
const void *arg2);
108 bool is_unique =
false;
135 checkingunique =
false;
155 insertstate.
itup = itup;
213 &is_unique, &speculativeToken);
226 if (speculativeToken)
261 indexUnchanged, stack, heapRel);
263 stack, itup, insertstate.
itemsz, newitemoff,
425 bool inposting =
false;
426 bool prevalldead =
true;
471 if (offset <= maxoff)
510 bool all_dead =
false;
528 htid = curitup->
t_tid;
589 SnapshotDirty.
xmin : SnapshotDirty.
xmax;
669 (
errcode(ERRCODE_UNIQUE_VIOLATION),
670 errmsg(
"duplicate key value violates unique constraint \"%s\"",
672 key_desc ?
errdetail(
"Key %s already exists.",
678 else if (all_dead && (!inposting ||
704 if (!all_dead && inposting)
715 else if (offset < maxoff)
744 elog(
ERROR,
"fell off the end of index \"%s\"",
763 (
errcode(ERRCODE_INTERNAL_ERROR),
764 errmsg(
"failed to re-find tuple within index \"%s\"",
766 errhint(
"This may be because of a non-immutable index expression."),
845 bool uniquedup = indexUnchanged;
907 checkingunique, uniquedup,
950 false,
false,
false);
1001 false,
false,
false);
1065 elog(
ERROR,
"fell off the end of index \"%s\"",
1072 insertstate->
buf = rbuf;
1117 bool split_only_page)
1161 if (postingoff != 0)
1188 (
errcode(ERRCODE_INDEX_CORRUPTED),
1189 errmsg_internal(
"table tid from new index tuple (%u,%u) overlaps with invalid duplicate tuple at offset %u of block %u in index \"%s\"",
1216 Assert(!split_only_page);
1219 rbuf =
_bt_split(rel, heaprel, itup_key,
buf, cbuf, newitemoff, itemsz,
1220 itup, origitup, nposting, postingoff);
1243#ifdef USE_INJECTION_POINTS
1286 if (postingoff != 0)
1290 elog(
PANIC,
"failed to add new item to block %u in index \"%s\"",
1315 cpageop->
btpo_flags &= ~BTP_INCOMPLETE_SPLIT;
1328 xlrec.
offnum = newitemoff;
1333 if (isleaf && postingoff == 0)
1338 else if (postingoff != 0)
1375 if (postingoff == 0)
1390 upostingoff = postingoff;
1420 if (isrightmost && isleaf && !isroot)
1439 if (postingoff != 0)
1553 newitem, &newitemonleft);
1556 leftpage = leftpage_buf.
data;
1599 if (postingoff != 0)
1603 &newitem->
t_tid) < 0);
1628 if (!newitemonleft && newitemoff == firstrightoff)
1632 firstright = newitem;
1640 if (firstrightoff == origpagepostingoff)
1641 firstright = nposting;
1649 if (newitemonleft && newitemoff == firstrightoff)
1663 if (lastleftoff == origpagepostingoff)
1664 lastleft = nposting;
1667 lefthighkey =
_bt_truncate(rel, lastleft, firstright, itup_key);
1698 lefthighkey = firstright;
1711 elog(
ERROR,
"failed to add high key to the left sibling"
1712 " while splitting block %u of index \"%s\"",
1727 rightpage = rightpage_buf.
data;
1782 elog(
ERROR,
"failed to add high key to the right sibling"
1783 " while splitting block %u of index \"%s\"",
1795 minusinfoff = afterrightoff;
1813 if (
i == origpagepostingoff)
1817 dataitem = nposting;
1821 else if (
i == newitemoff)
1825 Assert(newitemoff <= firstrightoff);
1826 if (!
_bt_pgaddtup(leftpage, newitemsz, newitem, afterleftoff,
1829 elog(
ERROR,
"failed to add new item to the left sibling"
1830 " while splitting block %u of index \"%s\"",
1837 Assert(newitemoff >= firstrightoff);
1838 if (!
_bt_pgaddtup(rightpage, newitemsz, newitem, afterrightoff,
1839 afterrightoff == minusinfoff))
1841 elog(
ERROR,
"failed to add new item to the right sibling"
1842 " while splitting block %u of index \"%s\"",
1850 if (
i < firstrightoff)
1852 if (!
_bt_pgaddtup(leftpage, itemsz, dataitem, afterleftoff,
false))
1854 elog(
ERROR,
"failed to add old item to the left sibling"
1855 " while splitting block %u of index \"%s\"",
1862 if (!
_bt_pgaddtup(rightpage, itemsz, dataitem, afterrightoff,
1863 afterrightoff == minusinfoff))
1865 elog(
ERROR,
"failed to add old item to the right sibling"
1866 " while splitting block %u of index \"%s\"",
1874 if (
i <= newitemoff)
1881 Assert(!newitemonleft && newitemoff == maxoff + 1);
1882 if (!
_bt_pgaddtup(rightpage, newitemsz, newitem, afterrightoff,
1883 afterrightoff == minusinfoff))
1885 elog(
ERROR,
"failed to add new item to the right sibling"
1886 " while splitting block %u of index \"%s\"",
1902 if (sopaque->
btpo_prev != origpagenumber)
1905 (
errcode(ERRCODE_INDEX_CORRUPTED),
1907 "block %u links to %u instead of expected %u in index \"%s\"",
1946 memcpy(origpage, leftpage, BLCKSZ);
1956 memcpy(rightpage, rightpage_buf.
data, BLCKSZ);
1977 cpageop->
btpo_flags &= ~BTP_INCOMPLETE_SPLIT;
1993 if (postingoff != 0 && origpagepostingoff < firstrightoff)
2039 Assert(newitemonleft || firstrightoff == newitemoff);
2065 (
char *) rightpage + ((
PageHeader) rightpage)->pd_upper,
2228 (
errcode(ERRCODE_INDEX_CORRUPTED),
2229 errmsg_internal(
"failed to re-find parent key in index \"%s\" for split pages %u/%u",
2297 elog(
DEBUG1,
"finishing incomplete split of %u/%u",
2391 for (offnum =
start;
2502 left_item->
t_info = left_item_sz;
2547 elog(
PANIC,
"failed to add leftkey to new root page"
2548 " while splitting block %u of index \"%s\"",
2558 elog(
PANIC,
"failed to add rightkey to new root page"
2559 " while splitting block %u of index \"%s\"",
2564 lopaque->
btpo_flags &= ~BTP_INCOMPLETE_SPLIT;
2589 md.
root = rootblknum;
2603 (
char *) rootpage + ((
PageHeader) rootpage)->pd_upper,
2648 bool newfirstdataitem)
2652 if (newfirstdataitem)
2698 bool simpleonly,
bool checkingunique,
2699 bool uniquedup,
bool indexUnchanged)
2713 Assert(!simpleonly || (!checkingunique && !uniquedup && !indexUnchanged));
2724 for (offnum = minoff;
2731 deletable[ndeletable++] = offnum;
2737 insertstate->
itup, minoff, maxoff);
2761 if (simpleonly || (checkingunique && !uniquedup))
2787 if ((indexUnchanged || uniquedup) &&
2794 (indexUnchanged || uniquedup));
2836 deadblocks =
_bt_deadblocks(page, deletable, ndeletable, newitem,
2840 delstate.
irel = rel;
2848 for (offnum = minoff;
2862 match = bsearch(&tidblock, deadblocks, ndeadblocks,
2888 for (
int p = 0; p < nitem; p++)
2893 match = bsearch(&tidblock, deadblocks, ndeadblocks,
2906 odeltid->
tid = *tid;
2964 spacentids = ndeletable + 1;
2976 for (
int i = 0;
i < ndeletable;
i++)
2985 if (ntids + 1 > spacentids)
2998 if (ntids + nposting > spacentids)
3000 spacentids =
Max(spacentids * 2, ntids + nposting);
3005 for (
int j = 0;
j < nposting;
j++)
#define InvalidBlockNumber
static bool BlockNumberIsValid(BlockNumber blockNumber)
static Datum values[MAXATTR]
BlockNumber BufferGetBlockNumber(Buffer buffer)
void ReleaseBuffer(Buffer buffer)
void MarkBufferDirty(Buffer buffer)
void MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
static Page BufferGetPage(Buffer buffer)
static Size BufferGetPageSize(Buffer buffer)
static bool BufferIsValid(Buffer bufnum)
Size PageGetFreeSpace(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)
static XLogRecPtr PageGetLSN(const PageData *page)
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
static OffsetNumber PageGetMaxOffsetNumber(const PageData *page)
int errmsg_internal(const char *fmt,...)
int errdetail(const char *fmt,...)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
char * BuildIndexValueDescription(Relation indexRelation, const Datum *values, const bool *isnull)
Assert(PointerIsAligned(start, uint64))
void index_deform_tuple(IndexTuple tup, TupleDesc tupleDescriptor, Datum *values, bool *isnull)
IndexTuple CopyIndexTuple(IndexTuple source)
#define INJECTION_POINT(name, arg)
static int pg_cmp_u32(uint32 a, uint32 b)
if(TABLE==NULL||TABLE_index==NULL)
#define ItemIdMarkDead(itemId)
#define ItemIdGetLength(itemId)
#define ItemIdIsDead(itemId)
int32 ItemPointerCompare(const ItemPointerData *arg1, const ItemPointerData *arg2)
static OffsetNumber ItemPointerGetOffsetNumber(const ItemPointerData *pointer)
static BlockNumber ItemPointerGetBlockNumber(const ItemPointerData *pointer)
IndexTupleData * IndexTuple
struct IndexTupleData IndexTupleData
static Size IndexTupleSize(const IndexTupleData *itup)
#define MaxIndexTuplesPerPage
void SpeculativeInsertionWait(TransactionId xid, uint32 token)
void XactLockTableWait(TransactionId xid, Relation rel, const ItemPointerData *ctid, XLTW_Oper oper)
void * repalloc(void *pointer, Size size)
void pfree(void *pointer)
#define START_CRIT_SECTION()
#define END_CRIT_SECTION()
IndexTuple _bt_swap_posting(IndexTuple newitem, IndexTuple oposting, int postingoff)
void _bt_dedup_pass(Relation rel, Buffer buf, IndexTuple newitem, Size newitemsz, bool bottomupdedup)
bool _bt_bottomupdel_pass(Relation rel, Buffer buf, Relation heapRel, Size newitemsz)
static BTStack _bt_search_insert(Relation rel, Relation heaprel, BTInsertState insertstate)
#define BTREE_FASTPATH_MIN_LEVEL
static OffsetNumber _bt_findinsertloc(Relation rel, BTInsertState insertstate, bool checkingunique, bool indexUnchanged, BTStack stack, Relation heapRel)
Buffer _bt_getstackbuf(Relation rel, Relation heaprel, BTStack stack, BlockNumber child)
static bool _bt_pgaddtup(Page page, Size itemsize, const IndexTupleData *itup, OffsetNumber itup_off, bool newfirstdataitem)
static void _bt_simpledel_pass(Relation rel, Buffer buffer, Relation heapRel, OffsetNumber *deletable, int ndeletable, IndexTuple newitem, OffsetNumber minoff, OffsetNumber maxoff)
bool _bt_doinsert(Relation rel, IndexTuple itup, IndexUniqueCheck checkUnique, bool indexUnchanged, Relation heapRel)
static Buffer _bt_newlevel(Relation rel, Relation heaprel, Buffer lbuf, Buffer rbuf)
static void _bt_insert_parent(Relation rel, Relation heaprel, Buffer buf, Buffer rbuf, BTStack stack, bool isroot, bool isonly)
static void _bt_delete_or_dedup_one_page(Relation rel, Relation heapRel, BTInsertState insertstate, bool simpleonly, bool checkingunique, bool uniquedup, bool indexUnchanged)
void _bt_finish_split(Relation rel, Relation heaprel, Buffer lbuf, BTStack stack)
static Buffer _bt_split(Relation rel, Relation heaprel, 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 _bt_stepright(Relation rel, Relation heaprel, BTInsertState insertstate, BTStack stack)
static void _bt_insertonpg(Relation rel, Relation heaprel, BTScanInsert itup_key, Buffer buf, Buffer cbuf, BTStack stack, IndexTuple itup, Size itemsz, OffsetNumber newitemoff, int postingoff, bool split_only_page)
static TransactionId _bt_check_unique(Relation rel, BTInsertState insertstate, Relation heapRel, IndexUniqueCheck checkUnique, bool *is_unique, uint32 *speculativeToken)
static BlockNumber * _bt_deadblocks(Page page, OffsetNumber *deletable, int ndeletable, IndexTuple newitem, int *nblocks)
Buffer _bt_relandgetbuf(Relation rel, Buffer obuf, BlockNumber blkno, int access)
void _bt_upgrademetapage(Page page)
void _bt_relbuf(Relation rel, Buffer buf)
int _bt_getrootheight(Relation rel)
void _bt_pageinit(Page page, Size size)
Buffer _bt_allocbuf(Relation rel, Relation heaprel)
void _bt_checkpage(Relation rel, Buffer buf)
bool _bt_conditionallockbuf(Relation rel, Buffer buf)
Buffer _bt_getbuf(Relation rel, BlockNumber blkno, int access)
void _bt_delitems_delete_check(Relation rel, Buffer buf, Relation heapRel, TM_IndexDeleteOp *delstate)
#define BTGetDeduplicateItems(relation)
static uint16 BTreeTupleGetNPosting(IndexTuple posting)
static bool BTreeTupleIsPivot(IndexTuple itup)
#define P_HAS_GARBAGE(opaque)
#define P_LEFTMOST(opaque)
#define BTPageGetOpaque(page)
#define MaxTIDsPerBTreePage
static void BTreeTupleSetDownLink(IndexTuple pivot, BlockNumber blkno)
#define P_FIRSTDATAKEY(opaque)
#define P_RIGHTMOST(opaque)
#define P_INCOMPLETE_SPLIT(opaque)
#define BTP_INCOMPLETE_SPLIT
static ItemPointer BTreeTupleGetPostingN(IndexTuple posting, int n)
static BlockNumber BTreeTupleGetDownLink(IndexTuple pivot)
static bool BTreeTupleIsPosting(IndexTuple itup)
#define BTREE_NOVAC_VERSION
static void BTreeTupleSetNAtts(IndexTuple itup, uint16 nkeyatts, bool heaptid)
#define BTreeTupleGetNAtts(itup, rel)
Buffer _bt_get_endpoint(Relation rel, uint32 level, bool rightmost)
BTStack _bt_search(Relation rel, Relation heaprel, BTScanInsert key, Buffer *bufP, int access)
OffsetNumber _bt_binsrch_insert(Relation rel, BTInsertState insertstate)
int32 _bt_compare(Relation rel, BTScanInsert key, Page page, OffsetNumber offnum)
OffsetNumber _bt_findsplitloc(Relation rel, Page origpage, OffsetNumber newitemoff, Size newitemsz, IndexTuple newitem, bool *newitemonleft)
void _bt_check_third_page(Relation rel, Relation heap, bool needheaptidspace, Page page, IndexTuple newtup)
void _bt_freestack(BTStack stack)
BTCycleId _bt_vacuum_cycleid(Relation rel)
BTScanInsert _bt_mkscankey(Relation rel, IndexTuple itup)
IndexTuple _bt_truncate(Relation rel, IndexTuple lastleft, IndexTuple firstright, BTScanInsert itup_key)
#define XLOG_BTREE_INSERT_POST
#define SizeOfBtreeInsert
#define XLOG_BTREE_SPLIT_R
#define XLOG_BTREE_INSERT_LEAF
#define XLOG_BTREE_INSERT_UPPER
#define SizeOfBtreeNewroot
#define XLOG_BTREE_INSERT_META
#define XLOG_BTREE_SPLIT_L
#define XLOG_BTREE_NEWROOT
#define InvalidOffsetNumber
#define OffsetNumberNext(offsetNumber)
#define OffsetNumberPrev(offsetNumber)
uint32 pg_prng_uint32(pg_prng_state *state)
pg_prng_state pg_global_prng_state
#define qsort(a, b, c, d)
void PredicateLockPageSplit(Relation relation, BlockNumber oldblkno, BlockNumber newblkno)
void CheckForSerializableConflictIn(Relation relation, const ItemPointerData *tid, BlockNumber blkno)
static size_t qunique(void *array, size_t elements, size_t width, int(*compare)(const void *, const void *))
#define RelationGetDescr(relation)
#define RelationGetRelationName(relation)
#define RelationGetTargetBlock(relation)
#define RelationNeedsWAL(relation)
#define RelationSetTargetBlock(relation, targblock)
#define IndexRelationGetNumberOfAttributes(relation)
#define IndexRelationGetNumberOfKeyAttributes(relation)
int errtableconstraint(Relation rel, const char *conname)
#define InitDirtySnapshot(snapshotdata)
uint32 btm_last_cleanup_num_delpages
struct BTStackData * bts_parent
OffsetNumber firstrightoff
bool table_index_fetch_tuple_check(Relation rel, ItemPointer tid, Snapshot snapshot, bool *all_dead)
#define InvalidTransactionId
#define TransactionIdIsValid(xid)
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
void XLogRegisterBufData(uint8 block_id, const void *data, uint32 len)
void XLogRegisterData(const void *data, uint32 len)
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
void XLogBeginInsert(void)