1 | /*------------------------------------------------------------------------- |
2 | * |
3 | * postgres.h |
4 | * Primary include file for PostgreSQL server .c files |
5 | * |
6 | * This should be the first file included by PostgreSQL backend modules. |
7 | * Client-side code should include postgres_fe.h instead. |
8 | * |
9 | * |
10 | * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group |
11 | * Portions Copyright (c) 1995, Regents of the University of California |
12 | * |
13 | * src/include/postgres.h |
14 | * |
15 | *------------------------------------------------------------------------- |
16 | */ |
17 | /* |
18 | *---------------------------------------------------------------- |
19 | * TABLE OF CONTENTS |
20 | * |
21 | * When adding stuff to this file, please try to put stuff |
22 | * into the relevant section, or add new sections as appropriate. |
23 | * |
24 | * section description |
25 | * ------- ------------------------------------------------ |
26 | * 1) variable-length datatypes (TOAST support) |
27 | * 2) Datum type + support macros |
28 | * |
29 | * NOTES |
30 | * |
31 | * In general, this file should contain declarations that are widely needed |
32 | * in the backend environment, but are of no interest outside the backend. |
33 | * |
34 | * Simple type definitions live in c.h, where they are shared with |
35 | * postgres_fe.h. We do that since those type definitions are needed by |
36 | * frontend modules that want to deal with binary data transmission to or |
37 | * from the backend. Type definitions in this file should be for |
38 | * representations that never escape the backend, such as Datum or |
39 | * TOASTed varlena objects. |
40 | * |
41 | *---------------------------------------------------------------- |
42 | */ |
43 | #ifndef POSTGRES_H |
44 | #define POSTGRES_H |
45 | |
46 | #include "c.h" |
47 | #include "utils/elog.h" |
48 | #include "utils/palloc.h" |
49 | |
50 | /* ---------------------------------------------------------------- |
51 | * Section 1: variable-length datatypes (TOAST support) |
52 | * ---------------------------------------------------------------- |
53 | */ |
54 | |
55 | /* |
56 | * struct varatt_external is a traditional "TOAST pointer", that is, the |
57 | * information needed to fetch a Datum stored out-of-line in a TOAST table. |
58 | * The data is compressed if and only if va_extsize < va_rawsize - VARHDRSZ. |
59 | * This struct must not contain any padding, because we sometimes compare |
60 | * these pointers using memcmp. |
61 | * |
62 | * Note that this information is stored unaligned within actual tuples, so |
63 | * you need to memcpy from the tuple into a local struct variable before |
64 | * you can look at these fields! (The reason we use memcmp is to avoid |
65 | * having to do that just to detect equality of two TOAST pointers...) |
66 | */ |
67 | typedef struct varatt_external |
68 | { |
69 | int32 va_rawsize; /* Original data size (includes header) */ |
70 | int32 va_extsize; /* External saved size (doesn't) */ |
71 | Oid va_valueid; /* Unique ID of value within TOAST table */ |
72 | Oid va_toastrelid; /* RelID of TOAST table containing it */ |
73 | } varatt_external; |
74 | |
75 | /* |
76 | * struct varatt_indirect is a "TOAST pointer" representing an out-of-line |
77 | * Datum that's stored in memory, not in an external toast relation. |
78 | * The creator of such a Datum is entirely responsible that the referenced |
79 | * storage survives for as long as referencing pointer Datums can exist. |
80 | * |
81 | * Note that just as for struct varatt_external, this struct is stored |
82 | * unaligned within any containing tuple. |
83 | */ |
84 | typedef struct varatt_indirect |
85 | { |
86 | struct varlena *pointer; /* Pointer to in-memory varlena */ |
87 | } varatt_indirect; |
88 | |
89 | /* |
90 | * struct varatt_expanded is a "TOAST pointer" representing an out-of-line |
91 | * Datum that is stored in memory, in some type-specific, not necessarily |
92 | * physically contiguous format that is convenient for computation not |
93 | * storage. APIs for this, in particular the definition of struct |
94 | * ExpandedObjectHeader, are in src/include/utils/expandeddatum.h. |
95 | * |
96 | * Note that just as for struct varatt_external, this struct is stored |
97 | * unaligned within any containing tuple. |
98 | */ |
99 | typedef struct ExpandedObjectHeader ExpandedObjectHeader; |
100 | |
101 | typedef struct varatt_expanded |
102 | { |
103 | ExpandedObjectHeader *eohptr; |
104 | } varatt_expanded; |
105 | |
106 | /* |
107 | * Type tag for the various sorts of "TOAST pointer" datums. The peculiar |
108 | * value for VARTAG_ONDISK comes from a requirement for on-disk compatibility |
109 | * with a previous notion that the tag field was the pointer datum's length. |
110 | */ |
111 | typedef enum vartag_external |
112 | { |
113 | VARTAG_INDIRECT = 1, |
114 | VARTAG_EXPANDED_RO = 2, |
115 | VARTAG_EXPANDED_RW = 3, |
116 | VARTAG_ONDISK = 18 |
117 | } vartag_external; |
118 | |
119 | /* this test relies on the specific tag values above */ |
120 | #define VARTAG_IS_EXPANDED(tag) \ |
121 | (((tag) & ~1) == VARTAG_EXPANDED_RO) |
122 | |
123 | #define VARTAG_SIZE(tag) \ |
124 | ((tag) == VARTAG_INDIRECT ? sizeof(varatt_indirect) : \ |
125 | VARTAG_IS_EXPANDED(tag) ? sizeof(varatt_expanded) : \ |
126 | (tag) == VARTAG_ONDISK ? sizeof(varatt_external) : \ |
127 | TrapMacro(true, "unrecognized TOAST vartag")) |
128 | |
129 | /* |
130 | * These structs describe the header of a varlena object that may have been |
131 | * TOASTed. Generally, don't reference these structs directly, but use the |
132 | * macros below. |
133 | * |
134 | * We use separate structs for the aligned and unaligned cases because the |
135 | * compiler might otherwise think it could generate code that assumes |
136 | * alignment while touching fields of a 1-byte-header varlena. |
137 | */ |
138 | typedef union |
139 | { |
140 | struct /* Normal varlena (4-byte length) */ |
141 | { |
142 | uint32 ; |
143 | char va_data[FLEXIBLE_ARRAY_MEMBER]; |
144 | } va_4byte; |
145 | struct /* Compressed-in-line format */ |
146 | { |
147 | uint32 ; |
148 | uint32 va_rawsize; /* Original data size (excludes header) */ |
149 | char va_data[FLEXIBLE_ARRAY_MEMBER]; /* Compressed data */ |
150 | } va_compressed; |
151 | } varattrib_4b; |
152 | |
153 | typedef struct |
154 | { |
155 | uint8 ; |
156 | char va_data[FLEXIBLE_ARRAY_MEMBER]; /* Data begins here */ |
157 | } varattrib_1b; |
158 | |
159 | /* TOAST pointers are a subset of varattrib_1b with an identifying tag byte */ |
160 | typedef struct |
161 | { |
162 | uint8 ; /* Always 0x80 or 0x01 */ |
163 | uint8 va_tag; /* Type of datum */ |
164 | char va_data[FLEXIBLE_ARRAY_MEMBER]; /* Type-specific data */ |
165 | } varattrib_1b_e; |
166 | |
167 | /* |
168 | * Bit layouts for varlena headers on big-endian machines: |
169 | * |
170 | * 00xxxxxx 4-byte length word, aligned, uncompressed data (up to 1G) |
171 | * 01xxxxxx 4-byte length word, aligned, *compressed* data (up to 1G) |
172 | * 10000000 1-byte length word, unaligned, TOAST pointer |
173 | * 1xxxxxxx 1-byte length word, unaligned, uncompressed data (up to 126b) |
174 | * |
175 | * Bit layouts for varlena headers on little-endian machines: |
176 | * |
177 | * xxxxxx00 4-byte length word, aligned, uncompressed data (up to 1G) |
178 | * xxxxxx10 4-byte length word, aligned, *compressed* data (up to 1G) |
179 | * 00000001 1-byte length word, unaligned, TOAST pointer |
180 | * xxxxxxx1 1-byte length word, unaligned, uncompressed data (up to 126b) |
181 | * |
182 | * The "xxx" bits are the length field (which includes itself in all cases). |
183 | * In the big-endian case we mask to extract the length, in the little-endian |
184 | * case we shift. Note that in both cases the flag bits are in the physically |
185 | * first byte. Also, it is not possible for a 1-byte length word to be zero; |
186 | * this lets us disambiguate alignment padding bytes from the start of an |
187 | * unaligned datum. (We now *require* pad bytes to be filled with zero!) |
188 | * |
189 | * In TOAST pointers the va_tag field (see varattrib_1b_e) is used to discern |
190 | * the specific type and length of the pointer datum. |
191 | */ |
192 | |
193 | /* |
194 | * Endian-dependent macros. These are considered internal --- use the |
195 | * external macros below instead of using these directly. |
196 | * |
197 | * Note: IS_1B is true for external toast records but VARSIZE_1B will return 0 |
198 | * for such records. Hence you should usually check for IS_EXTERNAL before |
199 | * checking for IS_1B. |
200 | */ |
201 | |
202 | #ifdef WORDS_BIGENDIAN |
203 | |
204 | #define VARATT_IS_4B(PTR) \ |
205 | ((((varattrib_1b *) (PTR))->va_header & 0x80) == 0x00) |
206 | #define VARATT_IS_4B_U(PTR) \ |
207 | ((((varattrib_1b *) (PTR))->va_header & 0xC0) == 0x00) |
208 | #define VARATT_IS_4B_C(PTR) \ |
209 | ((((varattrib_1b *) (PTR))->va_header & 0xC0) == 0x40) |
210 | #define VARATT_IS_1B(PTR) \ |
211 | ((((varattrib_1b *) (PTR))->va_header & 0x80) == 0x80) |
212 | #define VARATT_IS_1B_E(PTR) \ |
213 | ((((varattrib_1b *) (PTR))->va_header) == 0x80) |
214 | #define VARATT_NOT_PAD_BYTE(PTR) \ |
215 | (*((uint8 *) (PTR)) != 0) |
216 | |
217 | /* VARSIZE_4B() should only be used on known-aligned data */ |
218 | #define VARSIZE_4B(PTR) \ |
219 | (((varattrib_4b *) (PTR))->va_4byte.va_header & 0x3FFFFFFF) |
220 | #define VARSIZE_1B(PTR) \ |
221 | (((varattrib_1b *) (PTR))->va_header & 0x7F) |
222 | #define VARTAG_1B_E(PTR) \ |
223 | (((varattrib_1b_e *) (PTR))->va_tag) |
224 | |
225 | #define SET_VARSIZE_4B(PTR,len) \ |
226 | (((varattrib_4b *) (PTR))->va_4byte.va_header = (len) & 0x3FFFFFFF) |
227 | #define SET_VARSIZE_4B_C(PTR,len) \ |
228 | (((varattrib_4b *) (PTR))->va_4byte.va_header = ((len) & 0x3FFFFFFF) | 0x40000000) |
229 | #define SET_VARSIZE_1B(PTR,len) \ |
230 | (((varattrib_1b *) (PTR))->va_header = (len) | 0x80) |
231 | #define SET_VARTAG_1B_E(PTR,tag) \ |
232 | (((varattrib_1b_e *) (PTR))->va_header = 0x80, \ |
233 | ((varattrib_1b_e *) (PTR))->va_tag = (tag)) |
234 | #else /* !WORDS_BIGENDIAN */ |
235 | |
236 | #define VARATT_IS_4B(PTR) \ |
237 | ((((varattrib_1b *) (PTR))->va_header & 0x01) == 0x00) |
238 | #define VARATT_IS_4B_U(PTR) \ |
239 | ((((varattrib_1b *) (PTR))->va_header & 0x03) == 0x00) |
240 | #define VARATT_IS_4B_C(PTR) \ |
241 | ((((varattrib_1b *) (PTR))->va_header & 0x03) == 0x02) |
242 | #define VARATT_IS_1B(PTR) \ |
243 | ((((varattrib_1b *) (PTR))->va_header & 0x01) == 0x01) |
244 | #define VARATT_IS_1B_E(PTR) \ |
245 | ((((varattrib_1b *) (PTR))->va_header) == 0x01) |
246 | #define VARATT_NOT_PAD_BYTE(PTR) \ |
247 | (*((uint8 *) (PTR)) != 0) |
248 | |
249 | /* VARSIZE_4B() should only be used on known-aligned data */ |
250 | #define VARSIZE_4B(PTR) \ |
251 | ((((varattrib_4b *) (PTR))->va_4byte.va_header >> 2) & 0x3FFFFFFF) |
252 | #define VARSIZE_1B(PTR) \ |
253 | ((((varattrib_1b *) (PTR))->va_header >> 1) & 0x7F) |
254 | #define VARTAG_1B_E(PTR) \ |
255 | (((varattrib_1b_e *) (PTR))->va_tag) |
256 | |
257 | #define SET_VARSIZE_4B(PTR,len) \ |
258 | (((varattrib_4b *) (PTR))->va_4byte.va_header = (((uint32) (len)) << 2)) |
259 | #define SET_VARSIZE_4B_C(PTR,len) \ |
260 | (((varattrib_4b *) (PTR))->va_4byte.va_header = (((uint32) (len)) << 2) | 0x02) |
261 | #define SET_VARSIZE_1B(PTR,len) \ |
262 | (((varattrib_1b *) (PTR))->va_header = (((uint8) (len)) << 1) | 0x01) |
263 | #define SET_VARTAG_1B_E(PTR,tag) \ |
264 | (((varattrib_1b_e *) (PTR))->va_header = 0x01, \ |
265 | ((varattrib_1b_e *) (PTR))->va_tag = (tag)) |
266 | #endif /* WORDS_BIGENDIAN */ |
267 | |
268 | #define VARHDRSZ_SHORT offsetof(varattrib_1b, va_data) |
269 | #define VARATT_SHORT_MAX 0x7F |
270 | #define VARATT_CAN_MAKE_SHORT(PTR) \ |
271 | (VARATT_IS_4B_U(PTR) && \ |
272 | (VARSIZE(PTR) - VARHDRSZ + VARHDRSZ_SHORT) <= VARATT_SHORT_MAX) |
273 | #define VARATT_CONVERTED_SHORT_SIZE(PTR) \ |
274 | (VARSIZE(PTR) - VARHDRSZ + VARHDRSZ_SHORT) |
275 | |
276 | #define VARHDRSZ_EXTERNAL offsetof(varattrib_1b_e, va_data) |
277 | |
278 | #define VARDATA_4B(PTR) (((varattrib_4b *) (PTR))->va_4byte.va_data) |
279 | #define VARDATA_4B_C(PTR) (((varattrib_4b *) (PTR))->va_compressed.va_data) |
280 | #define VARDATA_1B(PTR) (((varattrib_1b *) (PTR))->va_data) |
281 | #define VARDATA_1B_E(PTR) (((varattrib_1b_e *) (PTR))->va_data) |
282 | |
283 | #define VARRAWSIZE_4B_C(PTR) \ |
284 | (((varattrib_4b *) (PTR))->va_compressed.va_rawsize) |
285 | |
286 | /* Externally visible macros */ |
287 | |
288 | /* |
289 | * In consumers oblivious to data alignment, call PG_DETOAST_DATUM_PACKED(), |
290 | * VARDATA_ANY(), VARSIZE_ANY() and VARSIZE_ANY_EXHDR(). Elsewhere, call |
291 | * PG_DETOAST_DATUM(), VARDATA() and VARSIZE(). Directly fetching an int16, |
292 | * int32 or wider field in the struct representing the datum layout requires |
293 | * aligned data. memcpy() is alignment-oblivious, as are most operations on |
294 | * datatypes, such as text, whose layout struct contains only char fields. |
295 | * |
296 | * Code assembling a new datum should call VARDATA() and SET_VARSIZE(). |
297 | * (Datums begin life untoasted.) |
298 | * |
299 | * Other macros here should usually be used only by tuple assembly/disassembly |
300 | * code and code that specifically wants to work with still-toasted Datums. |
301 | */ |
302 | #define VARDATA(PTR) VARDATA_4B(PTR) |
303 | #define VARSIZE(PTR) VARSIZE_4B(PTR) |
304 | |
305 | #define VARSIZE_SHORT(PTR) VARSIZE_1B(PTR) |
306 | #define VARDATA_SHORT(PTR) VARDATA_1B(PTR) |
307 | |
308 | #define VARTAG_EXTERNAL(PTR) VARTAG_1B_E(PTR) |
309 | #define VARSIZE_EXTERNAL(PTR) (VARHDRSZ_EXTERNAL + VARTAG_SIZE(VARTAG_EXTERNAL(PTR))) |
310 | #define VARDATA_EXTERNAL(PTR) VARDATA_1B_E(PTR) |
311 | |
312 | #define VARATT_IS_COMPRESSED(PTR) VARATT_IS_4B_C(PTR) |
313 | #define VARATT_IS_EXTERNAL(PTR) VARATT_IS_1B_E(PTR) |
314 | #define VARATT_IS_EXTERNAL_ONDISK(PTR) \ |
315 | (VARATT_IS_EXTERNAL(PTR) && VARTAG_EXTERNAL(PTR) == VARTAG_ONDISK) |
316 | #define VARATT_IS_EXTERNAL_INDIRECT(PTR) \ |
317 | (VARATT_IS_EXTERNAL(PTR) && VARTAG_EXTERNAL(PTR) == VARTAG_INDIRECT) |
318 | #define VARATT_IS_EXTERNAL_EXPANDED_RO(PTR) \ |
319 | (VARATT_IS_EXTERNAL(PTR) && VARTAG_EXTERNAL(PTR) == VARTAG_EXPANDED_RO) |
320 | #define VARATT_IS_EXTERNAL_EXPANDED_RW(PTR) \ |
321 | (VARATT_IS_EXTERNAL(PTR) && VARTAG_EXTERNAL(PTR) == VARTAG_EXPANDED_RW) |
322 | #define VARATT_IS_EXTERNAL_EXPANDED(PTR) \ |
323 | (VARATT_IS_EXTERNAL(PTR) && VARTAG_IS_EXPANDED(VARTAG_EXTERNAL(PTR))) |
324 | #define VARATT_IS_EXTERNAL_NON_EXPANDED(PTR) \ |
325 | (VARATT_IS_EXTERNAL(PTR) && !VARTAG_IS_EXPANDED(VARTAG_EXTERNAL(PTR))) |
326 | #define VARATT_IS_SHORT(PTR) VARATT_IS_1B(PTR) |
327 | #define VARATT_IS_EXTENDED(PTR) (!VARATT_IS_4B_U(PTR)) |
328 | |
329 | #define SET_VARSIZE(PTR, len) SET_VARSIZE_4B(PTR, len) |
330 | #define SET_VARSIZE_SHORT(PTR, len) SET_VARSIZE_1B(PTR, len) |
331 | #define SET_VARSIZE_COMPRESSED(PTR, len) SET_VARSIZE_4B_C(PTR, len) |
332 | |
333 | #define SET_VARTAG_EXTERNAL(PTR, tag) SET_VARTAG_1B_E(PTR, tag) |
334 | |
335 | #define VARSIZE_ANY(PTR) \ |
336 | (VARATT_IS_1B_E(PTR) ? VARSIZE_EXTERNAL(PTR) : \ |
337 | (VARATT_IS_1B(PTR) ? VARSIZE_1B(PTR) : \ |
338 | VARSIZE_4B(PTR))) |
339 | |
340 | /* Size of a varlena data, excluding header */ |
341 | #define VARSIZE_ANY_EXHDR(PTR) \ |
342 | (VARATT_IS_1B_E(PTR) ? VARSIZE_EXTERNAL(PTR)-VARHDRSZ_EXTERNAL : \ |
343 | (VARATT_IS_1B(PTR) ? VARSIZE_1B(PTR)-VARHDRSZ_SHORT : \ |
344 | VARSIZE_4B(PTR)-VARHDRSZ)) |
345 | |
346 | /* caution: this will not work on an external or compressed-in-line Datum */ |
347 | /* caution: this will return a possibly unaligned pointer */ |
348 | #define VARDATA_ANY(PTR) \ |
349 | (VARATT_IS_1B(PTR) ? VARDATA_1B(PTR) : VARDATA_4B(PTR)) |
350 | |
351 | |
352 | /* ---------------------------------------------------------------- |
353 | * Section 2: Datum type + support macros |
354 | * ---------------------------------------------------------------- |
355 | */ |
356 | |
357 | /* |
358 | * A Datum contains either a value of a pass-by-value type or a pointer to a |
359 | * value of a pass-by-reference type. Therefore, we require: |
360 | * |
361 | * sizeof(Datum) == sizeof(void *) == 4 or 8 |
362 | * |
363 | * The macros below and the analogous macros for other types should be used to |
364 | * convert between a Datum and the appropriate C type. |
365 | */ |
366 | |
367 | typedef uintptr_t Datum; |
368 | |
369 | /* |
370 | * A NullableDatum is used in places where both a Datum and its nullness needs |
371 | * to be stored. This can be more efficient than storing datums and nullness |
372 | * in separate arrays, due to better spatial locality, even if more space may |
373 | * be wasted due to padding. |
374 | */ |
375 | typedef struct NullableDatum |
376 | { |
377 | #define FIELDNO_NULLABLE_DATUM_DATUM 0 |
378 | Datum value; |
379 | #define FIELDNO_NULLABLE_DATUM_ISNULL 1 |
380 | bool isnull; |
381 | /* due to alignment padding this could be used for flags for free */ |
382 | } NullableDatum; |
383 | |
384 | #define SIZEOF_DATUM SIZEOF_VOID_P |
385 | |
386 | /* |
387 | * DatumGetBool |
388 | * Returns boolean value of a datum. |
389 | * |
390 | * Note: any nonzero value will be considered true. |
391 | */ |
392 | |
393 | #define DatumGetBool(X) ((bool) ((X) != 0)) |
394 | |
395 | /* |
396 | * BoolGetDatum |
397 | * Returns datum representation for a boolean. |
398 | * |
399 | * Note: any nonzero value will be considered true. |
400 | */ |
401 | |
402 | #define BoolGetDatum(X) ((Datum) ((X) ? 1 : 0)) |
403 | |
404 | /* |
405 | * DatumGetChar |
406 | * Returns character value of a datum. |
407 | */ |
408 | |
409 | #define DatumGetChar(X) ((char) (X)) |
410 | |
411 | /* |
412 | * CharGetDatum |
413 | * Returns datum representation for a character. |
414 | */ |
415 | |
416 | #define CharGetDatum(X) ((Datum) (X)) |
417 | |
418 | /* |
419 | * Int8GetDatum |
420 | * Returns datum representation for an 8-bit integer. |
421 | */ |
422 | |
423 | #define Int8GetDatum(X) ((Datum) (X)) |
424 | |
425 | /* |
426 | * DatumGetUInt8 |
427 | * Returns 8-bit unsigned integer value of a datum. |
428 | */ |
429 | |
430 | #define DatumGetUInt8(X) ((uint8) (X)) |
431 | |
432 | /* |
433 | * UInt8GetDatum |
434 | * Returns datum representation for an 8-bit unsigned integer. |
435 | */ |
436 | |
437 | #define UInt8GetDatum(X) ((Datum) (X)) |
438 | |
439 | /* |
440 | * DatumGetInt16 |
441 | * Returns 16-bit integer value of a datum. |
442 | */ |
443 | |
444 | #define DatumGetInt16(X) ((int16) (X)) |
445 | |
446 | /* |
447 | * Int16GetDatum |
448 | * Returns datum representation for a 16-bit integer. |
449 | */ |
450 | |
451 | #define Int16GetDatum(X) ((Datum) (X)) |
452 | |
453 | /* |
454 | * DatumGetUInt16 |
455 | * Returns 16-bit unsigned integer value of a datum. |
456 | */ |
457 | |
458 | #define DatumGetUInt16(X) ((uint16) (X)) |
459 | |
460 | /* |
461 | * UInt16GetDatum |
462 | * Returns datum representation for a 16-bit unsigned integer. |
463 | */ |
464 | |
465 | #define UInt16GetDatum(X) ((Datum) (X)) |
466 | |
467 | /* |
468 | * DatumGetInt32 |
469 | * Returns 32-bit integer value of a datum. |
470 | */ |
471 | |
472 | #define DatumGetInt32(X) ((int32) (X)) |
473 | |
474 | /* |
475 | * Int32GetDatum |
476 | * Returns datum representation for a 32-bit integer. |
477 | */ |
478 | |
479 | #define Int32GetDatum(X) ((Datum) (X)) |
480 | |
481 | /* |
482 | * DatumGetUInt32 |
483 | * Returns 32-bit unsigned integer value of a datum. |
484 | */ |
485 | |
486 | #define DatumGetUInt32(X) ((uint32) (X)) |
487 | |
488 | /* |
489 | * UInt32GetDatum |
490 | * Returns datum representation for a 32-bit unsigned integer. |
491 | */ |
492 | |
493 | #define UInt32GetDatum(X) ((Datum) (X)) |
494 | |
495 | /* |
496 | * DatumGetObjectId |
497 | * Returns object identifier value of a datum. |
498 | */ |
499 | |
500 | #define DatumGetObjectId(X) ((Oid) (X)) |
501 | |
502 | /* |
503 | * ObjectIdGetDatum |
504 | * Returns datum representation for an object identifier. |
505 | */ |
506 | |
507 | #define ObjectIdGetDatum(X) ((Datum) (X)) |
508 | |
509 | /* |
510 | * DatumGetTransactionId |
511 | * Returns transaction identifier value of a datum. |
512 | */ |
513 | |
514 | #define DatumGetTransactionId(X) ((TransactionId) (X)) |
515 | |
516 | /* |
517 | * TransactionIdGetDatum |
518 | * Returns datum representation for a transaction identifier. |
519 | */ |
520 | |
521 | #define TransactionIdGetDatum(X) ((Datum) (X)) |
522 | |
523 | /* |
524 | * MultiXactIdGetDatum |
525 | * Returns datum representation for a multixact identifier. |
526 | */ |
527 | |
528 | #define MultiXactIdGetDatum(X) ((Datum) (X)) |
529 | |
530 | /* |
531 | * DatumGetCommandId |
532 | * Returns command identifier value of a datum. |
533 | */ |
534 | |
535 | #define DatumGetCommandId(X) ((CommandId) (X)) |
536 | |
537 | /* |
538 | * CommandIdGetDatum |
539 | * Returns datum representation for a command identifier. |
540 | */ |
541 | |
542 | #define CommandIdGetDatum(X) ((Datum) (X)) |
543 | |
544 | /* |
545 | * DatumGetPointer |
546 | * Returns pointer value of a datum. |
547 | */ |
548 | |
549 | #define DatumGetPointer(X) ((Pointer) (X)) |
550 | |
551 | /* |
552 | * PointerGetDatum |
553 | * Returns datum representation for a pointer. |
554 | */ |
555 | |
556 | #define PointerGetDatum(X) ((Datum) (X)) |
557 | |
558 | /* |
559 | * DatumGetCString |
560 | * Returns C string (null-terminated string) value of a datum. |
561 | * |
562 | * Note: C string is not a full-fledged Postgres type at present, |
563 | * but type input functions use this conversion for their inputs. |
564 | */ |
565 | |
566 | #define DatumGetCString(X) ((char *) DatumGetPointer(X)) |
567 | |
568 | /* |
569 | * CStringGetDatum |
570 | * Returns datum representation for a C string (null-terminated string). |
571 | * |
572 | * Note: C string is not a full-fledged Postgres type at present, |
573 | * but type output functions use this conversion for their outputs. |
574 | * Note: CString is pass-by-reference; caller must ensure the pointed-to |
575 | * value has adequate lifetime. |
576 | */ |
577 | |
578 | #define CStringGetDatum(X) PointerGetDatum(X) |
579 | |
580 | /* |
581 | * DatumGetName |
582 | * Returns name value of a datum. |
583 | */ |
584 | |
585 | #define DatumGetName(X) ((Name) DatumGetPointer(X)) |
586 | |
587 | /* |
588 | * NameGetDatum |
589 | * Returns datum representation for a name. |
590 | * |
591 | * Note: Name is pass-by-reference; caller must ensure the pointed-to |
592 | * value has adequate lifetime. |
593 | */ |
594 | |
595 | #define NameGetDatum(X) CStringGetDatum(NameStr(*(X))) |
596 | |
597 | /* |
598 | * DatumGetInt64 |
599 | * Returns 64-bit integer value of a datum. |
600 | * |
601 | * Note: this macro hides whether int64 is pass by value or by reference. |
602 | */ |
603 | |
604 | #ifdef USE_FLOAT8_BYVAL |
605 | #define DatumGetInt64(X) ((int64) (X)) |
606 | #else |
607 | #define DatumGetInt64(X) (* ((int64 *) DatumGetPointer(X))) |
608 | #endif |
609 | |
610 | /* |
611 | * Int64GetDatum |
612 | * Returns datum representation for a 64-bit integer. |
613 | * |
614 | * Note: if int64 is pass by reference, this function returns a reference |
615 | * to palloc'd space. |
616 | */ |
617 | |
618 | #ifdef USE_FLOAT8_BYVAL |
619 | #define Int64GetDatum(X) ((Datum) (X)) |
620 | #else |
621 | extern Datum Int64GetDatum(int64 X); |
622 | #endif |
623 | |
624 | /* |
625 | * DatumGetUInt64 |
626 | * Returns 64-bit unsigned integer value of a datum. |
627 | * |
628 | * Note: this macro hides whether int64 is pass by value or by reference. |
629 | */ |
630 | |
631 | #ifdef USE_FLOAT8_BYVAL |
632 | #define DatumGetUInt64(X) ((uint64) (X)) |
633 | #else |
634 | #define DatumGetUInt64(X) (* ((uint64 *) DatumGetPointer(X))) |
635 | #endif |
636 | |
637 | /* |
638 | * UInt64GetDatum |
639 | * Returns datum representation for a 64-bit unsigned integer. |
640 | * |
641 | * Note: if int64 is pass by reference, this function returns a reference |
642 | * to palloc'd space. |
643 | */ |
644 | |
645 | #ifdef USE_FLOAT8_BYVAL |
646 | #define UInt64GetDatum(X) ((Datum) (X)) |
647 | #else |
648 | #define UInt64GetDatum(X) Int64GetDatum((int64) (X)) |
649 | #endif |
650 | |
651 | /* |
652 | * Float <-> Datum conversions |
653 | * |
654 | * These have to be implemented as inline functions rather than macros, when |
655 | * passing by value, because many machines pass int and float function |
656 | * parameters/results differently; so we need to play weird games with unions. |
657 | */ |
658 | |
659 | /* |
660 | * DatumGetFloat4 |
661 | * Returns 4-byte floating point value of a datum. |
662 | * |
663 | * Note: this macro hides whether float4 is pass by value or by reference. |
664 | */ |
665 | |
666 | #ifdef USE_FLOAT4_BYVAL |
667 | static inline float4 |
668 | DatumGetFloat4(Datum X) |
669 | { |
670 | union |
671 | { |
672 | int32 value; |
673 | float4 retval; |
674 | } myunion; |
675 | |
676 | myunion.value = DatumGetInt32(X); |
677 | return myunion.retval; |
678 | } |
679 | #else |
680 | #define DatumGetFloat4(X) (* ((float4 *) DatumGetPointer(X))) |
681 | #endif |
682 | |
683 | /* |
684 | * Float4GetDatum |
685 | * Returns datum representation for a 4-byte floating point number. |
686 | * |
687 | * Note: if float4 is pass by reference, this function returns a reference |
688 | * to palloc'd space. |
689 | */ |
690 | #ifdef USE_FLOAT4_BYVAL |
691 | static inline Datum |
692 | Float4GetDatum(float4 X) |
693 | { |
694 | union |
695 | { |
696 | float4 value; |
697 | int32 retval; |
698 | } myunion; |
699 | |
700 | myunion.value = X; |
701 | return Int32GetDatum(myunion.retval); |
702 | } |
703 | #else |
704 | extern Datum Float4GetDatum(float4 X); |
705 | #endif |
706 | |
707 | /* |
708 | * DatumGetFloat8 |
709 | * Returns 8-byte floating point value of a datum. |
710 | * |
711 | * Note: this macro hides whether float8 is pass by value or by reference. |
712 | */ |
713 | |
714 | #ifdef USE_FLOAT8_BYVAL |
715 | static inline float8 |
716 | DatumGetFloat8(Datum X) |
717 | { |
718 | union |
719 | { |
720 | int64 value; |
721 | float8 retval; |
722 | } myunion; |
723 | |
724 | myunion.value = DatumGetInt64(X); |
725 | return myunion.retval; |
726 | } |
727 | #else |
728 | #define DatumGetFloat8(X) (* ((float8 *) DatumGetPointer(X))) |
729 | #endif |
730 | |
731 | /* |
732 | * Float8GetDatum |
733 | * Returns datum representation for an 8-byte floating point number. |
734 | * |
735 | * Note: if float8 is pass by reference, this function returns a reference |
736 | * to palloc'd space. |
737 | */ |
738 | |
739 | #ifdef USE_FLOAT8_BYVAL |
740 | static inline Datum |
741 | Float8GetDatum(float8 X) |
742 | { |
743 | union |
744 | { |
745 | float8 value; |
746 | int64 retval; |
747 | } myunion; |
748 | |
749 | myunion.value = X; |
750 | return Int64GetDatum(myunion.retval); |
751 | } |
752 | #else |
753 | extern Datum Float8GetDatum(float8 X); |
754 | #endif |
755 | |
756 | |
757 | /* |
758 | * Int64GetDatumFast |
759 | * Float8GetDatumFast |
760 | * Float4GetDatumFast |
761 | * |
762 | * These macros are intended to allow writing code that does not depend on |
763 | * whether int64, float8, float4 are pass-by-reference types, while not |
764 | * sacrificing performance when they are. The argument must be a variable |
765 | * that will exist and have the same value for as long as the Datum is needed. |
766 | * In the pass-by-ref case, the address of the variable is taken to use as |
767 | * the Datum. In the pass-by-val case, these will be the same as the non-Fast |
768 | * macros. |
769 | */ |
770 | |
771 | #ifdef USE_FLOAT8_BYVAL |
772 | #define Int64GetDatumFast(X) Int64GetDatum(X) |
773 | #define Float8GetDatumFast(X) Float8GetDatum(X) |
774 | #else |
775 | #define Int64GetDatumFast(X) PointerGetDatum(&(X)) |
776 | #define Float8GetDatumFast(X) PointerGetDatum(&(X)) |
777 | #endif |
778 | |
779 | #ifdef USE_FLOAT4_BYVAL |
780 | #define Float4GetDatumFast(X) Float4GetDatum(X) |
781 | #else |
782 | #define Float4GetDatumFast(X) PointerGetDatum(&(X)) |
783 | #endif |
784 | |
785 | #endif /* POSTGRES_H */ |
786 | |