@@ -282,29 +282,27 @@ typedef struct BTMetaPageData
282
282
*
283
283
* We store the number of columns present inside pivot tuples by abusing
284
284
* their t_tid offset field, since pivot tuples never need to store a real
285
- * offset (downlinks only need to store a block number in t_tid). The
285
+ * offset (pivot tuples generally store a downlink in t_tid, though ). The
286
286
* offset field only stores the number of columns/attributes when the
287
287
* INDEX_ALT_TID_MASK bit is set, which doesn't count the trailing heap
288
288
* TID column sometimes stored in pivot tuples -- that's represented by
289
289
* the presence of BT_PIVOT_HEAP_TID_ATTR. The INDEX_ALT_TID_MASK bit in
290
290
* t_info is always set on BTREE_VERSION 4 pivot tuples, since
291
291
* BTreeTupleIsPivot() must work reliably on heapkeyspace versions.
292
292
*
293
- * In version 3 indexes, the INDEX_ALT_TID_MASK flag might not be set in
294
- * pivot tuples. In that case, the number of key columns is implicitly
295
- * the same as the number of key columns in the index. It is not usually
296
- * set on version 2 indexes, which predate the introduction of INCLUDE
297
- * indexes. (Only explicitly truncated pivot tuples explicitly represent
298
- * the number of key columns on versions 2 and 3, whereas all pivot tuples
299
- * are formed using truncation on version 4. A version 2 index will have
300
- * it set for an internal page negative infinity item iff internal page
301
- * split occurred after upgrade to Postgres 11+.)
293
+ * In version 2 or version 3 (!heapkeyspace) indexes, INDEX_ALT_TID_MASK
294
+ * might not be set in pivot tuples. BTreeTupleIsPivot() won't work
295
+ * reliably as a result. The number of columns stored is implicitly the
296
+ * same as the number of columns in the index, just like any non-pivot
297
+ * tuple. (The number of columns stored should not vary, since suffix
298
+ * truncation of key columns is unsafe within any !heapkeyspace index.)
302
299
*
303
- * The 12 least significant offset bits from t_tid are used to represent
304
- * the number of columns in INDEX_ALT_TID_MASK tuples, leaving 4 status
305
- * bits (BT_RESERVED_OFFSET_MASK bits), 3 of which that are reserved for
306
- * future use. BT_OFFSET_MASK should be large enough to store any number
307
- * of columns/attributes <= INDEX_MAX_KEYS.
300
+ * The 12 least significant bits from t_tid's offset number are used to
301
+ * represent the number of key columns within a pivot tuple. This leaves 4
302
+ * status bits (BT_STATUS_OFFSET_MASK bits), which are shared by all tuples
303
+ * that have the INDEX_ALT_TID_MASK bit set (set in t_info) to store basic
304
+ * tuple metadata. BTreeTupleIsPivot() and BTreeTupleIsPosting() use the
305
+ * BT_STATUS_OFFSET_MASK bits.
308
306
*
309
307
* Sometimes non-pivot tuples also use a representation that repurposes
310
308
* t_tid to store metadata rather than a TID. PostgreSQL v13 introduced a
@@ -321,31 +319,24 @@ typedef struct BTMetaPageData
321
319
*
322
320
* Posting list tuples are recognized as such by having the
323
321
* INDEX_ALT_TID_MASK status bit set in t_info and the BT_IS_POSTING status
324
- * bit set in t_tid. These flags redefine the content of the posting
325
- * tuple's t_tid to store an offset to the posting list, as well as the
326
- * total number of posting list array elements.
322
+ * bit set in t_tid's offset number. These flags redefine the content of
323
+ * the posting tuple's t_tid to store the location of the posting list
324
+ * (instead of a block number), as well as the total number of heap TIDs
325
+ * present in the tuple (instead of a real offset number).
327
326
*
328
- * The 12 least significant offset bits from t_tid are used to represent
329
- * the number of posting items present in the tuple, leaving 4 status
330
- * bits (BT_RESERVED_OFFSET_MASK bits), 3 of which that are reserved for
331
- * future use. Like any non-pivot tuple, the number of columns stored is
332
- * always implicitly the total number in the index (in practice there can
333
- * never be non-key columns stored, since deduplication is not supported
334
- * with INCLUDE indexes). BT_OFFSET_MASK should be large enough to store
335
- * any number of posting list TIDs that might be present in a tuple (since
336
- * tuple size is subject to the INDEX_SIZE_MASK limit).
337
- *
338
- * Note well: The macros that deal with the number of attributes in tuples
339
- * assume that a tuple with INDEX_ALT_TID_MASK set must be a pivot tuple or
340
- * non-pivot posting tuple, and that a tuple without INDEX_ALT_TID_MASK set
341
- * must be a non-pivot tuple (or must have the same number of attributes as
342
- * the index has generally in the case of !heapkeyspace indexes).
327
+ * The 12 least significant bits from t_tid's offset number are used to
328
+ * represent the number of heap TIDs present in the tuple, leaving 4 status
329
+ * bits (the BT_STATUS_OFFSET_MASK bits). Like any non-pivot tuple, the
330
+ * number of columns stored is always implicitly the total number in the
331
+ * index (in practice there can never be non-key columns stored, since
332
+ * deduplication is not supported with INCLUDE indexes).
343
333
*/
344
334
#define INDEX_ALT_TID_MASK INDEX_AM_RESERVED_BIT
345
335
346
- /* Item pointer offset bits */
347
- #define BT_RESERVED_OFFSET_MASK 0xF000
336
+ /* Item pointer offset bit masks */
348
337
#define BT_OFFSET_MASK 0x0FFF
338
+ #define BT_STATUS_OFFSET_MASK 0xF000
339
+ /* BT_STATUS_OFFSET_MASK status bits */
349
340
#define BT_PIVOT_HEAP_TID_ATTR 0x1000
350
341
#define BT_IS_POSTING 0x2000
351
342
@@ -378,11 +369,13 @@ BTreeTupleIsPosting(IndexTuple itup)
378
369
}
379
370
380
371
static inline void
381
- BTreeTupleSetPosting (IndexTuple itup , int nhtids , int postingoffset )
372
+ BTreeTupleSetPosting (IndexTuple itup , uint16 nhtids , int postingoffset )
382
373
{
383
- Assert (nhtids > 1 && (nhtids & BT_OFFSET_MASK ) == nhtids );
374
+ Assert (nhtids > 1 );
375
+ Assert ((nhtids & BT_STATUS_OFFSET_MASK ) == 0 );
384
376
Assert ((size_t ) postingoffset == MAXALIGN (postingoffset ));
385
377
Assert (postingoffset < INDEX_SIZE_MASK );
378
+ Assert (!BTreeTupleIsPivot (itup ));
386
379
387
380
itup -> t_info |= INDEX_ALT_TID_MASK ;
388
381
ItemPointerSetOffsetNumber (& itup -> t_tid , (nhtids | BT_IS_POSTING ));
@@ -470,7 +463,7 @@ static inline void
470
463
BTreeTupleSetNAtts (IndexTuple itup , uint16 nkeyatts , bool heaptid )
471
464
{
472
465
Assert (nkeyatts <= INDEX_MAX_KEYS );
473
- Assert ((nkeyatts & BT_RESERVED_OFFSET_MASK ) == 0 );
466
+ Assert ((nkeyatts & BT_STATUS_OFFSET_MASK ) == 0 );
474
467
Assert (!heaptid || nkeyatts > 0 );
475
468
Assert (!BTreeTupleIsPivot (itup ) || nkeyatts == 0 );
476
469
0 commit comments