diff --git a/doc/src/sgml/xtypes.sgml b/doc/src/sgml/xtypes.sgml index bc84ccd1c4..c80126a119 100644 --- a/doc/src/sgml/xtypes.sgml +++ b/doc/src/sgml/xtypes.sgml @@ -1,4 +1,4 @@ - + User-Defined Types @@ -219,7 +219,7 @@ CREATE TYPE complex ( PostgreSQL automatically provides support for arrays of that type.arrayof user-defined - type For historical reasons, the array type + type The array type typically has the same name as the base type with the underscore character (_) prepended. @@ -240,15 +240,16 @@ CREATE TYPE complex ( If the values of your data type vary in size (in internal form), you should make the data type TOAST-able (see ). You should do this even if the data are always - too small to be compressed or stored externally because - Postgres can save space on small data using - TOAST as well. + too small to be compressed or stored externally, because + TOAST can save space on small data too, by reducing header + overhead. To do this, the internal representation must follow the standard layout for - variable-length data: the first four bytes must be an int32 - which is never accessed directly (customarily named vl_len_). You + variable-length data: the first four bytes must be a char[4] + field which is never accessed directly (customarily named + vl_len_). You must use SET_VARSIZE() to store the size of the datum in this field and VARSIZE() to retrieve it. The C functions operating on the data type must always be careful to unpack any @@ -265,12 +266,25 @@ CREATE TYPE complex ( to avoid some of the overhead of PG_DETOAST_DATUM. You can use PG_DETOAST_DATUM_PACKED instead (customarily hidden by defining a GETARG_DATATYPE_PP macro) and using the macros - VARSIZE_ANY_EXHDR and VARDATA_ANY macros. + VARSIZE_ANY_EXHDR and VARDATA_ANY to access + a potentially-packed datum. Again, the data returned by these macros is not aligned even if the data type definition specifies an alignment. If the alignment is important you must go through the regular PG_DETOAST_DATUM interface. + + + Older code frequently declares vl_len_ as an + int32 field instead of char[4]. This is OK as long as + the struct definition has other fields that have at least int32 + alignment. But it is dangerous to use such a struct definition when + working with a potentially unaligned datum; the compiler may take it as + license to assume the datum actually is aligned, leading to core dumps on + architectures that are strict about alignment. + + + For further details see the description of the command. diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c index ca49ec9d93..a7fd6d0984 100644 --- a/src/backend/access/heap/tuptoaster.c +++ b/src/backend/access/heap/tuptoaster.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.81 2008/01/01 19:45:46 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.82 2008/02/23 19:11:45 tgl Exp $ * * * INTERFACE ROUTINES @@ -65,7 +65,8 @@ #define VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr) \ do { \ varattrib_1b_e *attre = (varattrib_1b_e *) (attr); \ - Assert(VARSIZE_ANY_EXHDR(attre) == sizeof(toast_pointer)); \ + Assert(VARATT_IS_EXTERNAL(attre)); \ + Assert(VARSIZE_EXTERNAL(attre) == sizeof(toast_pointer) + VARHDRSZ_EXTERNAL); \ memcpy(&(toast_pointer), VARDATA_EXTERNAL(attre), sizeof(toast_pointer)); \ } while (0) diff --git a/src/include/c.h b/src/include/c.h index b66006200f..07a29d9cdf 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -12,7 +12,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/c.h,v 1.222 2008/01/01 19:45:56 momjian Exp $ + * $PostgreSQL: pgsql/src/include/c.h,v 1.223 2008/02/23 19:11:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -410,7 +410,7 @@ typedef struct */ struct varlena { - int32 vl_len_; /* Do not touch this field directly! */ + char vl_len_[4]; /* Do not touch this field directly! */ char vl_dat[1]; }; diff --git a/src/include/utils/inet.h b/src/include/utils/inet.h index d102573f05..793e120785 100644 --- a/src/include/utils/inet.h +++ b/src/include/utils/inet.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/inet.h,v 1.28 2008/01/01 19:45:59 momjian Exp $ + * $PostgreSQL: pgsql/src/include/utils/inet.h,v 1.29 2008/02/23 19:11:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -49,7 +49,7 @@ typedef struct */ typedef struct { - int32 vl_len_; /* Do not touch this field directly! */ + char vl_len_[4]; /* Do not touch this field directly! */ inet_struct inet_data; } inet;