PostgreSQL Source Code
git master
tupmacs.h
Go to the documentation of this file.
1
/*-------------------------------------------------------------------------
2
*
3
* tupmacs.h
4
* Tuple macros used by both index tuples and heap tuples.
5
*
6
*
7
* Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
8
* Portions Copyright (c) 1994, Regents of the University of California
9
*
10
* src/include/access/tupmacs.h
11
*
12
*-------------------------------------------------------------------------
13
*/
14
#ifndef TUPMACS_H
15
#define TUPMACS_H
16
17
#include "catalog/pg_type_d.h"
/* for TYPALIGN macros */
18
19
20
/*
21
* Check a tuple's null bitmap to determine whether the attribute is null.
22
* Note that a 0 in the null bitmap indicates a null, while 1 indicates
23
* non-null.
24
*/
25
#define att_isnull(ATT, BITS) (!((BITS)[(ATT) >> 3] & (1 << ((ATT) & 0x07))))
26
27
/*
28
* Given a Form_pg_attribute and a pointer into a tuple's data area,
29
* return the correct value or pointer.
30
*
31
* We return a Datum value in all cases. If the attribute has "byval" false,
32
* we return the same pointer into the tuple data area that we're passed.
33
* Otherwise, we return the correct number of bytes fetched from the data
34
* area and extended to Datum form.
35
*
36
* On machines where Datum is 8 bytes, we support fetching 8-byte byval
37
* attributes; otherwise, only 1, 2, and 4-byte values are supported.
38
*
39
* Note that T must already be properly aligned for this to work correctly.
40
*/
41
#define fetchatt(A,T) fetch_att(T, (A)->attbyval, (A)->attlen)
42
43
/*
44
* Same, but work from byval/len parameters rather than Form_pg_attribute.
45
*/
46
#if SIZEOF_DATUM == 8
47
48
#define fetch_att(T,attbyval,attlen) \
49
( \
50
(attbyval) ? \
51
( \
52
(attlen) == (int) sizeof(Datum) ? \
53
*((Datum *)(T)) \
54
: \
55
( \
56
(attlen) == (int) sizeof(int32) ? \
57
Int32GetDatum(*((int32 *)(T))) \
58
: \
59
( \
60
(attlen) == (int) sizeof(int16) ? \
61
Int16GetDatum(*((int16 *)(T))) \
62
: \
63
( \
64
AssertMacro((attlen) == 1), \
65
CharGetDatum(*((char *)(T))) \
66
) \
67
) \
68
) \
69
) \
70
: \
71
PointerGetDatum((char *) (T)) \
72
)
73
#else
/* SIZEOF_DATUM != 8 */
74
75
#define fetch_att(T,attbyval,attlen) \
76
( \
77
(attbyval) ? \
78
( \
79
(attlen) == (int) sizeof(int32) ? \
80
Int32GetDatum(*((int32 *)(T))) \
81
: \
82
( \
83
(attlen) == (int) sizeof(int16) ? \
84
Int16GetDatum(*((int16 *)(T))) \
85
: \
86
( \
87
AssertMacro((attlen) == 1), \
88
CharGetDatum(*((char *)(T))) \
89
) \
90
) \
91
) \
92
: \
93
PointerGetDatum((char *) (T)) \
94
)
95
#endif
/* SIZEOF_DATUM == 8 */
96
97
/*
98
* att_align_datum aligns the given offset as needed for a datum of alignment
99
* requirement attalign and typlen attlen. attdatum is the Datum variable
100
* we intend to pack into a tuple (it's only accessed if we are dealing with
101
* a varlena type). Note that this assumes the Datum will be stored as-is;
102
* callers that are intending to convert non-short varlena datums to short
103
* format have to account for that themselves.
104
*/
105
#define att_align_datum(cur_offset, attalign, attlen, attdatum) \
106
( \
107
((attlen) == -1 && VARATT_IS_SHORT(DatumGetPointer(attdatum))) ? \
108
(uintptr_t) (cur_offset) : \
109
att_align_nominal(cur_offset, attalign) \
110
)
111
112
/*
113
* att_align_pointer performs the same calculation as att_align_datum,
114
* but is used when walking a tuple. attptr is the current actual data
115
* pointer; when accessing a varlena field we have to "peek" to see if we
116
* are looking at a pad byte or the first byte of a 1-byte-header datum.
117
* (A zero byte must be either a pad byte, or the first byte of a correctly
118
* aligned 4-byte length word; in either case we can align safely. A non-zero
119
* byte must be either a 1-byte length word, or the first byte of a correctly
120
* aligned 4-byte length word; in either case we need not align.)
121
*
122
* Note: some callers pass a "char *" pointer for cur_offset. This is
123
* a bit of a hack but should work all right as long as uintptr_t is the
124
* correct width.
125
*/
126
#define att_align_pointer(cur_offset, attalign, attlen, attptr) \
127
( \
128
((attlen) == -1 && VARATT_NOT_PAD_BYTE(attptr)) ? \
129
(uintptr_t) (cur_offset) : \
130
att_align_nominal(cur_offset, attalign) \
131
)
132
133
/*
134
* att_align_nominal aligns the given offset as needed for a datum of alignment
135
* requirement attalign, ignoring any consideration of packed varlena datums.
136
* There are three main use cases for using this macro directly:
137
* * we know that the att in question is not varlena (attlen != -1);
138
* in this case it is cheaper than the above macros and just as good.
139
* * we need to estimate alignment padding cost abstractly, ie without
140
* reference to a real tuple. We must assume the worst case that
141
* all varlenas are aligned.
142
* * within arrays and multiranges, we unconditionally align varlenas (XXX this
143
* should be revisited, probably).
144
*
145
* The attalign cases are tested in what is hopefully something like their
146
* frequency of occurrence.
147
*/
148
#define att_align_nominal(cur_offset, attalign) \
149
( \
150
((attalign) == TYPALIGN_INT) ? INTALIGN(cur_offset) : \
151
(((attalign) == TYPALIGN_CHAR) ? (uintptr_t) (cur_offset) : \
152
(((attalign) == TYPALIGN_DOUBLE) ? DOUBLEALIGN(cur_offset) : \
153
( \
154
AssertMacro((attalign) == TYPALIGN_SHORT), \
155
SHORTALIGN(cur_offset) \
156
))) \
157
)
158
159
/*
160
* att_addlength_datum increments the given offset by the space needed for
161
* the given Datum variable. attdatum is only accessed if we are dealing
162
* with a variable-length attribute.
163
*/
164
#define att_addlength_datum(cur_offset, attlen, attdatum) \
165
att_addlength_pointer(cur_offset, attlen, DatumGetPointer(attdatum))
166
167
/*
168
* att_addlength_pointer performs the same calculation as att_addlength_datum,
169
* but is used when walking a tuple --- attptr is the pointer to the field
170
* within the tuple.
171
*
172
* Note: some callers pass a "char *" pointer for cur_offset. This is
173
* actually perfectly OK, but probably should be cleaned up along with
174
* the same practice for att_align_pointer.
175
*/
176
#define att_addlength_pointer(cur_offset, attlen, attptr) \
177
( \
178
((attlen) > 0) ? \
179
( \
180
(cur_offset) + (attlen) \
181
) \
182
: (((attlen) == -1) ? \
183
( \
184
(cur_offset) + VARSIZE_ANY(attptr) \
185
) \
186
: \
187
( \
188
AssertMacro((attlen) == -2), \
189
(cur_offset) + (strlen((char *) (attptr)) + 1) \
190
)) \
191
)
192
193
/*
194
* store_att_byval is a partial inverse of fetch_att: store a given Datum
195
* value into a tuple data area at the specified address. However, it only
196
* handles the byval case, because in typical usage the caller needs to
197
* distinguish by-val and by-ref cases anyway, and so a do-it-all macro
198
* wouldn't be convenient.
199
*/
200
#if SIZEOF_DATUM == 8
201
202
#define store_att_byval(T,newdatum,attlen) \
203
do { \
204
switch (attlen) \
205
{ \
206
case sizeof(char): \
207
*(char *) (T) = DatumGetChar(newdatum); \
208
break; \
209
case sizeof(int16): \
210
*(int16 *) (T) = DatumGetInt16(newdatum); \
211
break; \
212
case sizeof(int32): \
213
*(int32 *) (T) = DatumGetInt32(newdatum); \
214
break; \
215
case sizeof(Datum): \
216
*(Datum *) (T) = (newdatum); \
217
break; \
218
default: \
219
elog(ERROR, "unsupported byval length: %d", \
220
(int) (attlen)); \
221
break; \
222
} \
223
} while (0)
224
#else
/* SIZEOF_DATUM != 8 */
225
226
#define store_att_byval(T,newdatum,attlen) \
227
do { \
228
switch (attlen) \
229
{ \
230
case sizeof(char): \
231
*(char *) (T) = DatumGetChar(newdatum); \
232
break; \
233
case sizeof(int16): \
234
*(int16 *) (T) = DatumGetInt16(newdatum); \
235
break; \
236
case sizeof(int32): \
237
*(int32 *) (T) = DatumGetInt32(newdatum); \
238
break; \
239
default: \
240
elog(ERROR, "unsupported byval length: %d", \
241
(int) (attlen)); \
242
break; \
243
} \
244
} while (0)
245
#endif
/* SIZEOF_DATUM == 8 */
246
247
#endif
src
include
access
tupmacs.h
Generated on Mon Mar 8 2021 12:13:24 for PostgreSQL Source Code by
1.8.13