aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/nbtree/nbtsearch.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access/nbtree/nbtsearch.c')
-rw-r--r--src/backend/access/nbtree/nbtsearch.c63
1 files changed, 60 insertions, 3 deletions
diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c
index 51dca64e139..4c6fdcdd8aa 100644
--- a/src/backend/access/nbtree/nbtsearch.c
+++ b/src/backend/access/nbtree/nbtsearch.c
@@ -147,7 +147,7 @@ _bt_search(Relation rel, int keysz, ScanKey scankey, bool nextkey,
offnum = _bt_binsrch(rel, *bufP, keysz, scankey, nextkey);
itemid = PageGetItemId(page, offnum);
itup = (IndexTuple) PageGetItem(page, itemid);
- blkno = ItemPointerGetBlockNumber(&(itup->t_tid));
+ blkno = BTreeInnerTupleGetDownLink(itup);
par_blkno = BufferGetBlockNumber(*bufP);
/*
@@ -163,7 +163,7 @@ _bt_search(Relation rel, int keysz, ScanKey scankey, bool nextkey,
new_stack = (BTStack) palloc(sizeof(BTStackData));
new_stack->bts_blkno = par_blkno;
new_stack->bts_offset = offnum;
- memcpy(&new_stack->bts_btentry, itup, sizeof(IndexTupleData));
+ new_stack->bts_btentry = blkno;
new_stack->bts_parent = stack_in;
/* drop the read lock on the parent page, acquire one on the child */
@@ -437,6 +437,15 @@ _bt_compare(Relation rel,
int i;
/*
+ * Check tuple has correct number of attributes.
+ */
+ if (unlikely(!_bt_check_natts(rel, page, offnum)))
+ ereport(ERROR,
+ (errcode(ERRCODE_INTERNAL_ERROR),
+ errmsg("tuple has wrong number of attributes in index \"%s\"",
+ RelationGetRelationName(rel))));
+
+ /*
* Force result ">" if target item is first data item on an internal page
* --- see NOTE above.
*/
@@ -1833,7 +1842,7 @@ _bt_get_endpoint(Relation rel, uint32 level, bool rightmost,
offnum = P_FIRSTDATAKEY(opaque);
itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, offnum));
- blkno = ItemPointerGetBlockNumber(&(itup->t_tid));
+ blkno = BTreeInnerTupleGetDownLink(itup);
buf = _bt_relandgetbuf(rel, buf, blkno, BT_READ);
page = BufferGetPage(buf);
@@ -1959,3 +1968,51 @@ _bt_initialize_more_data(BTScanOpaque so, ScanDirection dir)
so->numKilled = 0; /* just paranoia */
so->markItemIndex = -1; /* ditto */
}
+
+/*
+ * Check if index tuple have appropriate number of attributes.
+ */
+bool
+_bt_check_natts(Relation index, Page page, OffsetNumber offnum)
+{
+ int16 natts = IndexRelationGetNumberOfAttributes(index);
+ int16 nkeyatts = IndexRelationGetNumberOfKeyAttributes(index);
+ ItemId itemid;
+ IndexTuple itup;
+ BTPageOpaque opaque = (BTPageOpaque) PageGetSpecialPointer(page);
+
+ /*
+ * Assert that mask allocated for number of keys in index tuple can fit
+ * maximum number of index keys.
+ */
+ StaticAssertStmt(BT_N_KEYS_OFFSET_MASK >= INDEX_MAX_KEYS,
+ "BT_N_KEYS_OFFSET_MASK can't fit INDEX_MAX_KEYS");
+
+ itemid = PageGetItemId(page, offnum);
+ itup = (IndexTuple) PageGetItem(page, itemid);
+
+ if (P_ISLEAF(opaque) && offnum >= P_FIRSTDATAKEY(opaque))
+ {
+ /*
+ * Regular leaf tuples have as every index attributes
+ */
+ return (BTreeTupGetNAtts(itup, index) == natts);
+ }
+ else if (!P_ISLEAF(opaque) && offnum == P_FIRSTDATAKEY(opaque))
+ {
+ /*
+ * Leftmost tuples on non-leaf pages have no attributes, or haven't
+ * INDEX_ALT_TID_MASK set in pg_upgraded indexes.
+ */
+ return (BTreeTupGetNAtts(itup, index) == 0 ||
+ ((itup->t_info & INDEX_ALT_TID_MASK) == 0));
+ }
+ else
+ {
+ /*
+ * Pivot tuples stored in non-leaf pages and hikeys of leaf pages
+ * contain only key attributes
+ */
+ return (BTreeTupGetNAtts(itup, index) == nkeyatts);
+ }
+}