Update comments for PG_DETOAST_PACKED and VARDATA_ANY on a structures

that require alignment.

Add a paragraph to the "User-Defined Types" chapter on using these
macros since it seems like they're a hit.

Gregory Stark
This commit is contained in:
Bruce Momjian 2007-05-15 17:39:54 +00:00
parent 39712d1184
commit 178214d2ae
3 changed files with 47 additions and 15 deletions

View File

@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/xtypes.sgml,v 1.28 2006/09/16 00:30:16 momjian Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/xtypes.sgml,v 1.29 2007/05/15 17:39:54 momjian Exp $ -->
<sect1 id="xtypes">
<title>User-Defined Types</title>
@ -237,20 +237,38 @@ CREATE TYPE complex (
<primary>TOAST</primary>
<secondary>and user-defined types</secondary>
</indexterm>
If the values of your data type might exceed a few hundred bytes in
size (in internal form), you should make the data type
<acronym>TOAST</>-able (see <xref linkend="storage-toast">).
To do this, the internal
representation must follow the standard layout for variable-length
data: the first four bytes must be an <type>int32</type> containing
the total length in bytes of the datum (including itself). The C
functions operating on the data type must be careful to unpack any
If the values of your data type vary in size (in internal form), you should
make the data type <acronym>TOAST</>-able (see <xref
linkend="storage-toast">). You should do this even if the data are always
too small to be compressed or stored externally because
<productname>Postgres</> can save space on small data using
<acronym>TOAST</> as well.
</para>
<para>
To do this, the internal representation must follow the standard layout for
variable-length data: the first four bytes must be an <type>int32</type>
which is never accessed directly (customarily named <literal>vl_len_</>). You
must use <function>SET_VARSIZE()</function> to store the size of the datum
in this field and <function>VARSIZE()</function> to retrieve it. The C
functions operating on the data type must always be careful to unpack any
toasted values they are handed, by using <function>PG_DETOAST_DATUM</>.
(This detail is customarily hidden by defining type-specific
<function>GETARG</function> macros.) Then,
when running the <command>CREATE TYPE</command> command, specify the
internal length as <literal>variable</> and select the appropriate
storage option.
<function>GETARG_DATATYPE_P</function> macros.) Then, when running the
<command>CREATE TYPE</command> command, specify the internal length as
<literal>variable</> and select the appropriate storage option.
</para>
<para>
If the alignment is unimportant (either just for a specific function or
because the data type specifies byte alignment anyways) then it's possible
to avoid some of the overhead of <function>PG_DETOAST_DATUM</>. You can use
<function>PG_DETOAST_DATUM_PACKED</> instead (customarily hidden by
defining a <function>GETARG_DATATYPE_PP</> macro) and using the macros
<function>VARSIZE_ANY_EXHDR</> and <function>VARDATA_ANY</> macros.
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 <function>PG_DETOAST_DATUM</> interface.
</para>
<para>

View File

@ -11,7 +11,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/fmgr.h,v 1.50 2007/04/06 04:21:44 tgl Exp $
* $PostgreSQL: pgsql/src/include/fmgr.h,v 1.51 2007/05/15 17:39:54 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -158,6 +158,12 @@ extern void fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo,
* The resulting datum can be accessed using VARSIZE_ANY() and VARDATA_ANY()
* (beware of multiple evaluations in those macros!)
*
* WARNING: It is only safe to use PG_DETOAST_DATUM_UNPACKED() and
* VARDATA_ANY() if you really don't care about the alignment. Either because
* you're working with something like text where the alignment doesn't matter
* or because you're not going to access its constituent parts and just use
* things like memcpy on it anyways.
*
* Note: it'd be nice if these could be macros, but I see no way to do that
* without evaluating the arguments multiple times, which is NOT acceptable.
*/
@ -174,6 +180,7 @@ extern struct varlena *pg_detoast_datum_packed(struct varlena * datum);
#define PG_DETOAST_DATUM_SLICE(datum,f,c) \
pg_detoast_datum_slice((struct varlena *) DatumGetPointer(datum), \
(int32) f, (int32) c)
/* WARNING -- unaligned pointer */
#define PG_DETOAST_DATUM_PACKED(datum) \
pg_detoast_datum_packed((struct varlena *) DatumGetPointer(datum))

View File

@ -10,7 +10,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1995, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/postgres.h,v 1.80 2007/05/04 02:01:02 tgl Exp $
* $PostgreSQL: pgsql/src/include/postgres.h,v 1.81 2007/05/15 17:39:54 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -235,6 +235,12 @@ typedef struct
* use VARSIZE_ANY/VARSIZE_ANY_EXHDR/VARDATA_ANY. The other macros here
* should usually be used only by tuple assembly/disassembly code and
* code that specifically wants to work with still-toasted Datums.
*
* WARNING: It is only safe to use VARDATA_ANY() -- typically with
* PG_DETOAST_DATUM_UNPACKED() -- if you really don't care about the alignment.
* Either because you're working with something like text where the alignment
* doesn't matter or because you're not going to access its constituent parts
* and just use things like memcpy on it anyways.
*/
#define VARDATA(PTR) VARDATA_4B(PTR)
#define VARSIZE(PTR) VARSIZE_4B(PTR)
@ -265,6 +271,7 @@ typedef struct
VARSIZE_4B(PTR)-4))
/* caution: this will not work on an external or compressed-in-line Datum */
/* caution: this will return a possibly unaligned pointer */
#define VARDATA_ANY(PTR) \
(VARATT_IS_1B(PTR) ? VARDATA_1B(PTR) : VARDATA_4B(PTR))