240 lines
7.5 KiB
C
240 lines
7.5 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* tuptoaster.h
|
|
* POSTGRES definitions for external and compressed storage
|
|
* of variable size attributes.
|
|
*
|
|
* Copyright (c) 2000-2019, 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_build_flattened_tuple -
|
|
*
|
|
* Build a tuple containing no out-of-line toasted fields.
|
|
* (This does not eliminate compressed or short-header datums.)
|
|
* ----------
|
|
*/
|
|
extern HeapTuple toast_build_flattened_tuple(TupleDesc tupleDesc,
|
|
Datum *values,
|
|
bool *isnull);
|
|
|
|
/* ----------
|
|
* 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 */
|