diff options
Diffstat (limited to 'src/include/access/tupmacs.h')
-rw-r--r-- | src/include/access/tupmacs.h | 83 |
1 files changed, 70 insertions, 13 deletions
diff --git a/src/include/access/tupmacs.h b/src/include/access/tupmacs.h index 80c2d436f04..f4fb8c7b33d 100644 --- a/src/include/access/tupmacs.h +++ b/src/include/access/tupmacs.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/tupmacs.h,v 1.32 2007/02/27 23:48:09 tgl Exp $ + * $PostgreSQL: pgsql/src/include/access/tupmacs.h,v 1.33 2007/04/06 04:21:43 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -91,26 +91,83 @@ #endif /* SIZEOF_DATUM == 8 */ /* - * att_align aligns the given offset as needed for a datum of alignment - * requirement attalign. The cases are tested in what is hopefully something - * like their frequency of occurrence. + * att_align_datum aligns the given offset as needed for a datum of alignment + * requirement attalign and typlen attlen. attdatum is the Datum variable + * we intend to pack into a tuple (it's only accessed if we are dealing with + * a varlena type). Note that this assumes the Datum will be stored as-is; + * callers that are intending to convert non-short varlena datums to short + * format have to account for that themselves. */ -#define att_align(cur_offset, attalign) \ +#define att_align_datum(cur_offset, attalign, attlen, attdatum) \ +( \ + ((attlen) == -1 && VARATT_IS_SHORT(DatumGetPointer(attdatum))) ? (long) (cur_offset) : \ + att_align_nominal(cur_offset, attalign) \ +) + +/* + * att_align_pointer performs the same calculation as att_align_datum, + * but is used when walking a tuple. attptr is the current actual data + * pointer; when accessing a varlena field we have to "peek" to see if we + * are looking at a pad byte or the first byte of a 1-byte-header datum. + * (A zero byte must be either a pad byte, or the first byte of a correctly + * aligned 4-byte length word; in either case we can align safely. A non-zero + * byte must be either a 1-byte length word, or the first byte of a correctly + * aligned 4-byte length word; in either case we need not align.) + * + * Note: some callers pass a "char *" pointer for cur_offset. This is + * a bit of a hack but works OK on all known platforms. It ought to be + * cleaned up someday, though. + */ +#define att_align_pointer(cur_offset, attalign, attlen, attptr) \ +( \ + ((attlen) == -1 && VARATT_NOT_PAD_BYTE(attptr)) ? (long) (cur_offset) : \ + att_align_nominal(cur_offset, attalign) \ +) + +/* + * att_align_nominal aligns the given offset as needed for a datum of alignment + * requirement attalign, ignoring any consideration of packed varlena datums. + * There are three main use cases for using this macro directly: + * * we know that the att in question is not varlena (attlen != -1); + * in this case it is cheaper than the above macros and just as good. + * * we need to estimate alignment padding cost abstractly, ie without + * reference to a real tuple. We must assume the worst case that + * all varlenas are aligned. + * * within arrays, we unconditionally align varlenas (XXX this should be + * revisited, probably). + * + * The attalign cases are tested in what is hopefully something like their + * frequency of occurrence. + */ +#define att_align_nominal(cur_offset, attalign) \ ( \ ((attalign) == 'i') ? INTALIGN(cur_offset) : \ - (((attalign) == 'c') ? ((long)(cur_offset)) : \ + (((attalign) == 'c') ? (long) (cur_offset) : \ (((attalign) == 'd') ? DOUBLEALIGN(cur_offset) : \ - ( \ + ( \ AssertMacro((attalign) == 's'), \ SHORTALIGN(cur_offset) \ - ))) \ + ))) \ ) /* - * att_addlength increments the given offset by the length of the attribute. - * attval is only accessed if we are dealing with a variable-length attribute. + * att_addlength_datum increments the given offset by the space needed for + * the given Datum variable. attdatum is only accessed if we are dealing + * with a variable-length attribute. + */ +#define att_addlength_datum(cur_offset, attlen, attdatum) \ + att_addlength_pointer(cur_offset, attlen, DatumGetPointer(attdatum)) + +/* + * att_addlength_pointer performs the same calculation as att_addlength_datum, + * but is used when walking a tuple --- attptr is the pointer to the field + * within the tuple. + * + * Note: some callers pass a "char *" pointer for cur_offset. This is + * actually perfectly OK, but probably should be cleaned up along with + * the same practice for att_align_pointer. */ -#define att_addlength(cur_offset, attlen, attval) \ +#define att_addlength_pointer(cur_offset, attlen, attptr) \ ( \ ((attlen) > 0) ? \ ( \ @@ -118,12 +175,12 @@ ) \ : (((attlen) == -1) ? \ ( \ - (cur_offset) + VARSIZE(DatumGetPointer(attval)) \ + (cur_offset) + VARSIZE_ANY(attptr) \ ) \ : \ ( \ AssertMacro((attlen) == -2), \ - (cur_offset) + (strlen(DatumGetCString(attval)) + 1) \ + (cur_offset) + (strlen((char *) (attptr)) + 1) \ )) \ ) |