| 1 | /*------------------------------------------------------------------------- |
| 2 | * |
| 3 | * itup.h |
| 4 | * POSTGRES index tuple definitions. |
| 5 | * |
| 6 | * |
| 7 | * Portions Copyright (c) 1996-2019, 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 | /* |
| 77 | * Takes an infomask as argument (primarily because this needs to be usable |
| 78 | * at index_form_tuple time so enough space is allocated). |
| 79 | */ |
| 80 | #define IndexInfoFindDataOffset(t_info) \ |
| 81 | ( \ |
| 82 | (!((t_info) & INDEX_NULL_MASK)) ? \ |
| 83 | ( \ |
| 84 | (Size)MAXALIGN(sizeof(IndexTupleData)) \ |
| 85 | ) \ |
| 86 | : \ |
| 87 | ( \ |
| 88 | (Size)MAXALIGN(sizeof(IndexTupleData) + sizeof(IndexAttributeBitMapData)) \ |
| 89 | ) \ |
| 90 | ) |
| 91 | |
| 92 | /* ---------------- |
| 93 | * index_getattr |
| 94 | * |
| 95 | * This gets called many times, so we macro the cacheable and NULL |
| 96 | * lookups, and call nocache_index_getattr() for the rest. |
| 97 | * |
| 98 | * ---------------- |
| 99 | */ |
| 100 | #define index_getattr(tup, attnum, tupleDesc, isnull) \ |
| 101 | ( \ |
| 102 | AssertMacro(PointerIsValid(isnull) && (attnum) > 0), \ |
| 103 | *(isnull) = false, \ |
| 104 | !IndexTupleHasNulls(tup) ? \ |
| 105 | ( \ |
| 106 | TupleDescAttr((tupleDesc), (attnum)-1)->attcacheoff >= 0 ? \ |
| 107 | ( \ |
| 108 | fetchatt(TupleDescAttr((tupleDesc), (attnum)-1), \ |
| 109 | (char *) (tup) + IndexInfoFindDataOffset((tup)->t_info) \ |
| 110 | + TupleDescAttr((tupleDesc), (attnum)-1)->attcacheoff) \ |
| 111 | ) \ |
| 112 | : \ |
| 113 | nocache_index_getattr((tup), (attnum), (tupleDesc)) \ |
| 114 | ) \ |
| 115 | : \ |
| 116 | ( \ |
| 117 | (att_isnull((attnum)-1, (char *)(tup) + sizeof(IndexTupleData))) ? \ |
| 118 | ( \ |
| 119 | *(isnull) = true, \ |
| 120 | (Datum)NULL \ |
| 121 | ) \ |
| 122 | : \ |
| 123 | ( \ |
| 124 | nocache_index_getattr((tup), (attnum), (tupleDesc)) \ |
| 125 | ) \ |
| 126 | ) \ |
| 127 | ) |
| 128 | |
| 129 | /* |
| 130 | * MaxIndexTuplesPerPage is an upper bound on the number of tuples that can |
| 131 | * fit on one index page. An index tuple must have either data or a null |
| 132 | * bitmap, so we can safely assume it's at least 1 byte bigger than a bare |
| 133 | * IndexTupleData struct. We arrive at the divisor because each tuple |
| 134 | * must be maxaligned, and it must have an associated line pointer. |
| 135 | * |
| 136 | * To be index-type-independent, this does not account for any special space |
| 137 | * on the page, and is thus conservative. |
| 138 | * |
| 139 | * Note: in btree non-leaf pages, the first tuple has no key (it's implicitly |
| 140 | * minus infinity), thus breaking the "at least 1 byte bigger" assumption. |
| 141 | * On such a page, N tuples could take one MAXALIGN quantum less space than |
| 142 | * estimated here, seemingly allowing one more tuple than estimated here. |
| 143 | * But such a page always has at least MAXALIGN special space, so we're safe. |
| 144 | */ |
| 145 | #define MaxIndexTuplesPerPage \ |
| 146 | ((int) ((BLCKSZ - SizeOfPageHeaderData) / \ |
| 147 | (MAXALIGN(sizeof(IndexTupleData) + 1) + sizeof(ItemIdData)))) |
| 148 | |
| 149 | |
| 150 | /* routines in indextuple.c */ |
| 151 | extern IndexTuple index_form_tuple(TupleDesc tupleDescriptor, |
| 152 | Datum *values, bool *isnull); |
| 153 | extern Datum nocache_index_getattr(IndexTuple tup, int attnum, |
| 154 | TupleDesc tupleDesc); |
| 155 | extern void index_deform_tuple(IndexTuple tup, TupleDesc tupleDescriptor, |
| 156 | Datum *values, bool *isnull); |
| 157 | extern IndexTuple CopyIndexTuple(IndexTuple source); |
| 158 | extern IndexTuple index_truncate_tuple(TupleDesc sourceDescriptor, |
| 159 | IndexTuple source, int leavenatts); |
| 160 | |
| 161 | #endif /* ITUP_H */ |
| 162 | |