~ubuntu-branches/ubuntu/lucid/postgresql-8.4/lucid-proposed

« back to all changes in this revision

Viewing changes to src/include/access/tupmacs.h

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2009-03-20 12:00:13 UTC
  • Revision ID: james.westby@ubuntu.com-20090320120013-hogj7egc5mjncc5g
Tags: upstream-8.4~0cvs20090328
ImportĀ upstreamĀ versionĀ 8.4~0cvs20090328

Show diffs side-by-side

added added

removed removed

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