1 /*-------------------------------------------------------------------------
2  *
3  * heaptoast.h
4  *	  Heap-specific definitions for external and compressed storage
5  *	  of variable size attributes.
6  *
7  * Copyright (c) 2000-2021, PostgreSQL Global Development Group
8  *
9  * src/include/access/heaptoast.h
10  *
11  *-------------------------------------------------------------------------
12  */
13 #ifndef HEAPTOAST_H
14 #define HEAPTOAST_H
15 
16 #include "access/htup_details.h"
17 #include "storage/lockdefs.h"
18 #include "utils/relcache.h"
19 
20 /*
21  * Find the maximum size of a tuple if there are to be N tuples per page.
22  */
23 #define MaximumBytesPerTuple(tuplesPerPage) \
24 	MAXALIGN_DOWN((BLCKSZ - \
25 				   MAXALIGN(SizeOfPageHeaderData + (tuplesPerPage) * sizeof(ItemIdData))) \
26 				  / (tuplesPerPage))
27 
28 /*
29  * These symbols control toaster activation.  If a tuple is larger than
30  * TOAST_TUPLE_THRESHOLD, we will try to toast it down to no more than
31  * TOAST_TUPLE_TARGET bytes through compressing compressible fields and
32  * moving EXTENDED and EXTERNAL data out-of-line.
33  *
34  * The numbers need not be the same, though they currently are.  It doesn't
35  * make sense for TARGET to exceed THRESHOLD, but it could be useful to make
36  * it be smaller.
37  *
38  * Currently we choose both values to match the largest tuple size for which
39  * TOAST_TUPLES_PER_PAGE tuples can fit on a heap page.
40  *
41  * XXX while these can be modified without initdb, some thought needs to be
42  * given to needs_toast_table() in toasting.c before unleashing random
43  * changes.  Also see LOBLKSIZE in large_object.h, which can *not* be
44  * changed without initdb.
45  */
46 #define TOAST_TUPLES_PER_PAGE	4
47 
48 #define TOAST_TUPLE_THRESHOLD	MaximumBytesPerTuple(TOAST_TUPLES_PER_PAGE)
49 
50 #define TOAST_TUPLE_TARGET		TOAST_TUPLE_THRESHOLD
51 
52 /*
53  * The code will also consider moving MAIN data out-of-line, but only as a
54  * last resort if the previous steps haven't reached the target tuple size.
55  * In this phase we use a different target size, currently equal to the
56  * largest tuple that will fit on a heap page.  This is reasonable since
57  * the user has told us to keep the data in-line if at all possible.
58  */
59 #define TOAST_TUPLES_PER_PAGE_MAIN	1
60 
61 #define TOAST_TUPLE_TARGET_MAIN MaximumBytesPerTuple(TOAST_TUPLES_PER_PAGE_MAIN)
62 
63 /*
64  * If an index value is larger than TOAST_INDEX_TARGET, we will try to
65  * compress it (we can't move it out-of-line, however).  Note that this
66  * number is per-datum, not per-tuple, for simplicity in index_form_tuple().
67  */
68 #define TOAST_INDEX_TARGET		(MaxHeapTupleSize / 16)
69 
70 /*
71  * When we store an oversize datum externally, we divide it into chunks
72  * containing at most TOAST_MAX_CHUNK_SIZE data bytes.  This number *must*
73  * be small enough that the completed toast-table tuple (including the
74  * ID and sequence fields and all overhead) will fit on a page.
75  * The coding here sets the size on the theory that we want to fit
76  * EXTERN_TUPLES_PER_PAGE tuples of maximum size onto a page.
77  *
78  * NB: Changing TOAST_MAX_CHUNK_SIZE requires an initdb.
79  */
80 #define EXTERN_TUPLES_PER_PAGE	4	/* tweak only this */
81 
82 #define EXTERN_TUPLE_MAX_SIZE	MaximumBytesPerTuple(EXTERN_TUPLES_PER_PAGE)
83 
84 #define TOAST_MAX_CHUNK_SIZE	\
85 	(EXTERN_TUPLE_MAX_SIZE -							\
86 	 MAXALIGN(SizeofHeapTupleHeader) -					\
87 	 sizeof(Oid) -										\
88 	 sizeof(int32) -									\
89 	 VARHDRSZ)
90 
91 /* ----------
92  * heap_toast_insert_or_update -
93  *
94  *	Called by heap_insert() and heap_update().
95  * ----------
96  */
97 extern HeapTuple heap_toast_insert_or_update(Relation rel, HeapTuple newtup,
98 											 HeapTuple oldtup, int options);
99 
100 /* ----------
101  * heap_toast_delete -
102  *
103  *	Called by heap_delete().
104  * ----------
105  */
106 extern void heap_toast_delete(Relation rel, HeapTuple oldtup,
107 							  bool is_speculative);
108 
109 /* ----------
110  * toast_flatten_tuple -
111  *
112  *	"Flatten" a tuple to contain no out-of-line toasted fields.
113  *	(This does not eliminate compressed or short-header datums.)
114  * ----------
115  */
116 extern HeapTuple toast_flatten_tuple(HeapTuple tup, TupleDesc tupleDesc);
117 
118 /* ----------
119  * toast_flatten_tuple_to_datum -
120  *
121  *	"Flatten" a tuple containing out-of-line toasted fields into a Datum.
122  * ----------
123  */
124 extern Datum toast_flatten_tuple_to_datum(HeapTupleHeader tup,
125 										  uint32 tup_len,
126 										  TupleDesc tupleDesc);
127 
128 /* ----------
129  * toast_build_flattened_tuple -
130  *
131  *	Build a tuple containing no out-of-line toasted fields.
132  *	(This does not eliminate compressed or short-header datums.)
133  * ----------
134  */
135 extern HeapTuple toast_build_flattened_tuple(TupleDesc tupleDesc,
136 											 Datum *values,
137 											 bool *isnull);
138 
139 /* ----------
140  * heap_fetch_toast_slice
141  *
142  *	Fetch a slice from a toast value stored in a heap table.
143  * ----------
144  */
145 extern void heap_fetch_toast_slice(Relation toastrel, Oid valueid,
146 								   int32 attrsize, int32 sliceoffset,
147 								   int32 slicelength, struct varlena *result);
148 
149 #endif							/* HEAPTOAST_H */
150