Line data Source code
1 : /*------------------------------------------------------------------------- 2 : * 3 : * itup.h 4 : * POSTGRES index tuple definitions. 5 : * 6 : * 7 : * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group 8 : * Portions Copyright (c) 1994, Regents of the University of California 9 : * 10 : * src/include/access/itup.h 11 : * 12 : *------------------------------------------------------------------------- 13 : */ 14 : #ifndef ITUP_H 15 : #define ITUP_H 16 : 17 : #include "access/tupdesc.h" 18 : #include "access/tupmacs.h" 19 : #include "storage/bufpage.h" 20 : #include "storage/itemptr.h" 21 : 22 : /* 23 : * Index tuple header structure 24 : * 25 : * All index tuples start with IndexTupleData. If the HasNulls bit is set, 26 : * this is followed by an IndexAttributeBitMapData. The index attribute 27 : * values follow, beginning at a MAXALIGN boundary. 28 : * 29 : * Note that the space allocated for the bitmap does not vary with the number 30 : * of attributes; that is because we don't have room to store the number of 31 : * attributes in the header. Given the MAXALIGN constraint there's no space 32 : * savings to be had anyway, for usual values of INDEX_MAX_KEYS. 33 : */ 34 : 35 : typedef struct IndexTupleData 36 : { 37 : ItemPointerData t_tid; /* reference TID to heap tuple */ 38 : 39 : /* --------------- 40 : * t_info is laid out in the following fashion: 41 : * 42 : * 15th (high) bit: has nulls 43 : * 14th bit: has var-width attributes 44 : * 13th bit: AM-defined meaning 45 : * 12-0 bit: size of tuple 46 : * --------------- 47 : */ 48 : 49 : unsigned short t_info; /* various info about tuple */ 50 : 51 : } IndexTupleData; /* MORE DATA FOLLOWS AT END OF STRUCT */ 52 : 53 : typedef IndexTupleData *IndexTuple; 54 : 55 : typedef struct IndexAttributeBitMapData 56 : { 57 : bits8 bits[(INDEX_MAX_KEYS + 8 - 1) / 8]; 58 : } IndexAttributeBitMapData; 59 : 60 : typedef IndexAttributeBitMapData * IndexAttributeBitMap; 61 : 62 : /* 63 : * t_info manipulation macros 64 : */ 65 : #define INDEX_SIZE_MASK 0x1FFF 66 : #define INDEX_AM_RESERVED_BIT 0x2000 /* reserved for index-AM specific 67 : * usage */ 68 : #define INDEX_VAR_MASK 0x4000 69 : #define INDEX_NULL_MASK 0x8000 70 : 71 : #define IndexTupleSize(itup) ((Size) ((itup)->t_info & INDEX_SIZE_MASK)) 72 : #define IndexTupleHasNulls(itup) ((((IndexTuple) (itup))->t_info & INDEX_NULL_MASK)) 73 : #define IndexTupleHasVarwidths(itup) ((((IndexTuple) (itup))->t_info & INDEX_VAR_MASK)) 74 : 75 : 76 : /* routines in indextuple.c */ 77 : extern IndexTuple index_form_tuple(TupleDesc tupleDescriptor, 78 : const Datum *values, const bool *isnull); 79 : extern IndexTuple index_form_tuple_context(TupleDesc tupleDescriptor, 80 : const Datum *values, const bool *isnull, 81 : MemoryContext context); 82 : extern Datum nocache_index_getattr(IndexTuple tup, int attnum, 83 : TupleDesc tupleDesc); 84 : extern void index_deform_tuple(IndexTuple tup, TupleDesc tupleDescriptor, 85 : Datum *values, bool *isnull); 86 : extern void index_deform_tuple_internal(TupleDesc tupleDescriptor, 87 : Datum *values, bool *isnull, 88 : char *tp, bits8 *bp, int hasnulls); 89 : extern IndexTuple CopyIndexTuple(IndexTuple source); 90 : extern IndexTuple index_truncate_tuple(TupleDesc sourceDescriptor, 91 : IndexTuple source, int leavenatts); 92 : 93 : 94 : /* 95 : * Takes an infomask as argument (primarily because this needs to be usable 96 : * at index_form_tuple time so enough space is allocated). 97 : */ 98 : static inline Size 99 532962488 : IndexInfoFindDataOffset(unsigned short t_info) 100 : { 101 532962488 : if (!(t_info & INDEX_NULL_MASK)) 102 532739738 : return MAXALIGN(sizeof(IndexTupleData)); 103 : else 104 222750 : return MAXALIGN(sizeof(IndexTupleData) + sizeof(IndexAttributeBitMapData)); 105 : } 106 : 107 : #ifndef FRONTEND 108 : 109 : /* ---------------- 110 : * index_getattr 111 : * 112 : * This gets called many times, so we macro the cacheable and NULL 113 : * lookups, and call nocache_index_getattr() for the rest. 114 : * 115 : * ---------------- 116 : */ 117 : static inline Datum 118 497777826 : index_getattr(IndexTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull) 119 : { 120 : Assert(PointerIsValid(isnull)); 121 : Assert(attnum > 0); 122 : 123 497777826 : *isnull = false; 124 : 125 497777826 : if (!IndexTupleHasNulls(tup)) 126 : { 127 497059092 : CompactAttribute *attr = TupleDescCompactAttr(tupleDesc, attnum - 1); 128 : 129 497059092 : if (attr->attcacheoff >= 0) 130 : { 131 490900622 : return fetchatt(attr, 132 : (char *) tup + IndexInfoFindDataOffset(tup->t_info) + 133 : attr->attcacheoff); 134 : } 135 : else 136 6158470 : return nocache_index_getattr(tup, attnum, tupleDesc); 137 : } 138 : else 139 : { 140 718734 : if (att_isnull(attnum - 1, (bits8 *) tup + sizeof(IndexTupleData))) 141 : { 142 605494 : *isnull = true; 143 605494 : return (Datum) NULL; 144 : } 145 : else 146 113240 : return nocache_index_getattr(tup, attnum, tupleDesc); 147 : } 148 : } 149 : 150 : #endif 151 : 152 : /* 153 : * MaxIndexTuplesPerPage is an upper bound on the number of tuples that can 154 : * fit on one index page. An index tuple must have either data or a null 155 : * bitmap, so we can safely assume it's at least 1 byte bigger than a bare 156 : * IndexTupleData struct. We arrive at the divisor because each tuple 157 : * must be maxaligned, and it must have an associated line pointer. 158 : * 159 : * To be index-type-independent, this does not account for any special space 160 : * on the page, and is thus conservative. 161 : * 162 : * Note: in btree non-leaf pages, the first tuple has no key (it's implicitly 163 : * minus infinity), thus breaking the "at least 1 byte bigger" assumption. 164 : * On such a page, N tuples could take one MAXALIGN quantum less space than 165 : * estimated here, seemingly allowing one more tuple than estimated here. 166 : * But such a page always has at least MAXALIGN special space, so we're safe. 167 : */ 168 : #define MaxIndexTuplesPerPage \ 169 : ((int) ((BLCKSZ - SizeOfPageHeaderData) / \ 170 : (MAXALIGN(sizeof(IndexTupleData) + 1) + sizeof(ItemIdData)))) 171 : 172 : #endif /* ITUP_H */