123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- /*-------------------------------------------------------------------------
- *
- * tuptoaster.h
- * POSTGRES definitions for external and compressed storage
- * of variable size attributes.
- *
- * Copyright (c) 2000-2016, PostgreSQL Global Development Group
- *
- * src/include/access/tuptoaster.h
- *
- *-------------------------------------------------------------------------
- */
- #ifndef TUPTOASTER_H
- #define TUPTOASTER_H
- #include "access/htup_details.h"
- #include "storage/lockdefs.h"
- #include "utils/relcache.h"
- /*
- * This enables de-toasting of index entries. Needed until VACUUM is
- * smart enough to rebuild indexes from scratch.
- */
- #define TOAST_INDEX_HACK
- /*
- * Find the maximum size of a tuple if there are to be N tuples per page.
- */
- #define MaximumBytesPerTuple(tuplesPerPage) \
- MAXALIGN_DOWN((BLCKSZ - \
- MAXALIGN(SizeOfPageHeaderData + (tuplesPerPage) * sizeof(ItemIdData))) \
- / (tuplesPerPage))
- /*
- * These symbols control toaster activation. If a tuple is larger than
- * TOAST_TUPLE_THRESHOLD, we will try to toast it down to no more than
- * TOAST_TUPLE_TARGET bytes through compressing compressible fields and
- * moving EXTENDED and EXTERNAL data out-of-line.
- *
- * The numbers need not be the same, though they currently are. It doesn't
- * make sense for TARGET to exceed THRESHOLD, but it could be useful to make
- * it be smaller.
- *
- * Currently we choose both values to match the largest tuple size for which
- * TOAST_TUPLES_PER_PAGE tuples can fit on a heap page.
- *
- * XXX while these can be modified without initdb, some thought needs to be
- * given to needs_toast_table() in toasting.c before unleashing random
- * changes. Also see LOBLKSIZE in large_object.h, which can *not* be
- * changed without initdb.
- */
- #define TOAST_TUPLES_PER_PAGE 4
- #define TOAST_TUPLE_THRESHOLD MaximumBytesPerTuple(TOAST_TUPLES_PER_PAGE)
- #define TOAST_TUPLE_TARGET TOAST_TUPLE_THRESHOLD
- /*
- * The code will also consider moving MAIN data out-of-line, but only as a
- * last resort if the previous steps haven't reached the target tuple size.
- * In this phase we use a different target size, currently equal to the
- * largest tuple that will fit on a heap page. This is reasonable since
- * the user has told us to keep the data in-line if at all possible.
- */
- #define TOAST_TUPLES_PER_PAGE_MAIN 1
- #define TOAST_TUPLE_TARGET_MAIN MaximumBytesPerTuple(TOAST_TUPLES_PER_PAGE_MAIN)
- /*
- * If an index value is larger than TOAST_INDEX_TARGET, we will try to
- * compress it (we can't move it out-of-line, however). Note that this
- * number is per-datum, not per-tuple, for simplicity in index_form_tuple().
- */
- #define TOAST_INDEX_TARGET (MaxHeapTupleSize / 16)
- /*
- * When we store an oversize datum externally, we divide it into chunks
- * containing at most TOAST_MAX_CHUNK_SIZE data bytes. This number *must*
- * be small enough that the completed toast-table tuple (including the
- * ID and sequence fields and all overhead) will fit on a page.
- * The coding here sets the size on the theory that we want to fit
- * EXTERN_TUPLES_PER_PAGE tuples of maximum size onto a page.
- *
- * NB: Changing TOAST_MAX_CHUNK_SIZE requires an initdb.
- */
- #define EXTERN_TUPLES_PER_PAGE 4 /* tweak only this */
- #define EXTERN_TUPLE_MAX_SIZE MaximumBytesPerTuple(EXTERN_TUPLES_PER_PAGE)
- #define TOAST_MAX_CHUNK_SIZE \
- (EXTERN_TUPLE_MAX_SIZE - \
- MAXALIGN(SizeofHeapTupleHeader) - \
- sizeof(Oid) - \
- sizeof(int32) - \
- VARHDRSZ)
- /* Size of an EXTERNAL datum that contains a standard TOAST pointer */
- #define TOAST_POINTER_SIZE (VARHDRSZ_EXTERNAL + sizeof(varatt_external))
- /* Size of an EXTERNAL datum that contains an indirection pointer */
- #define INDIRECT_POINTER_SIZE (VARHDRSZ_EXTERNAL + sizeof(varatt_indirect))
- /*
- * Testing whether an externally-stored value is compressed now requires
- * comparing extsize (the actual length of the external data) to rawsize
- * (the original uncompressed datum's size). The latter includes VARHDRSZ
- * overhead, the former doesn't. We never use compression unless it actually
- * saves space, so we expect either equality or less-than.
- */
- #define VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer) \
- ((toast_pointer).va_extsize < (toast_pointer).va_rawsize - VARHDRSZ)
- /*
- * Macro to fetch the possibly-unaligned contents of an EXTERNAL datum
- * into a local "struct varatt_external" toast pointer. This should be
- * just a memcpy, but some versions of gcc seem to produce broken code
- * that assumes the datum contents are aligned. Introducing an explicit
- * intermediate "varattrib_1b_e *" variable seems to fix it.
- */
- #define VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr) \
- do { \
- varattrib_1b_e *attre = (varattrib_1b_e *) (attr); \
- 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)
- /* ----------
- * toast_insert_or_update -
- *
- * Called by heap_insert() and heap_update().
- * ----------
- */
- extern HeapTuple toast_insert_or_update(Relation rel,
- HeapTuple newtup, HeapTuple oldtup,
- int options);
- /* ----------
- * toast_delete -
- *
- * Called by heap_delete().
- * ----------
- */
- extern void toast_delete(Relation rel, HeapTuple oldtup, bool is_speculative);
- /* ----------
- * heap_tuple_fetch_attr() -
- *
- * Fetches an external stored attribute from the toast
- * relation. Does NOT decompress it, if stored external
- * in compressed format.
- * ----------
- */
- extern struct varlena *heap_tuple_fetch_attr(struct varlena * attr);
- /* ----------
- * heap_tuple_untoast_attr() -
- *
- * Fully detoasts one attribute, fetching and/or decompressing
- * it as needed.
- * ----------
- */
- extern struct varlena *heap_tuple_untoast_attr(struct varlena * attr);
- /* ----------
- * heap_tuple_untoast_attr_slice() -
- *
- * Fetches only the specified portion of an attribute.
- * (Handles all cases for attribute storage)
- * ----------
- */
- extern struct varlena *heap_tuple_untoast_attr_slice(struct varlena * attr,
- int32 sliceoffset,
- int32 slicelength);
- /* ----------
- * toast_flatten_tuple -
- *
- * "Flatten" a tuple to contain no out-of-line toasted fields.
- * (This does not eliminate compressed or short-header datums.)
- * ----------
- */
- extern HeapTuple toast_flatten_tuple(HeapTuple tup, TupleDesc tupleDesc);
- /* ----------
- * toast_flatten_tuple_to_datum -
- *
- * "Flatten" a tuple containing out-of-line toasted fields into a Datum.
- * ----------
- */
- extern Datum toast_flatten_tuple_to_datum(HeapTupleHeader tup,
- uint32 tup_len,
- TupleDesc tupleDesc);
- /* ----------
- * toast_compress_datum -
- *
- * Create a compressed version of a varlena datum, if possible
- * ----------
- */
- extern Datum toast_compress_datum(Datum value);
- /* ----------
- * toast_raw_datum_size -
- *
- * Return the raw (detoasted) size of a varlena datum
- * ----------
- */
- extern Size toast_raw_datum_size(Datum value);
- /* ----------
- * toast_datum_size -
- *
- * Return the storage size of a varlena datum
- * ----------
- */
- extern Size toast_datum_size(Datum value);
- /* ----------
- * toast_get_valid_index -
- *
- * Return OID of valid index associated to a toast relation
- * ----------
- */
- extern Oid toast_get_valid_index(Oid toastoid, LOCKMODE lock);
- #endif /* TUPTOASTER_H */
|