PostgreSQL Source Code  git master
tuptoaster.h File Reference
Include dependency graph for tuptoaster.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define TOAST_INDEX_HACK
 
#define MaximumBytesPerTuple(tuplesPerPage)
 
#define TOAST_TUPLES_PER_PAGE   4
 
#define TOAST_TUPLE_THRESHOLD   MaximumBytesPerTuple(TOAST_TUPLES_PER_PAGE)
 
#define TOAST_TUPLE_TARGET   TOAST_TUPLE_THRESHOLD
 
#define TOAST_TUPLES_PER_PAGE_MAIN   1
 
#define TOAST_TUPLE_TARGET_MAIN   MaximumBytesPerTuple(TOAST_TUPLES_PER_PAGE_MAIN)
 
#define TOAST_INDEX_TARGET   (MaxHeapTupleSize / 16)
 
#define EXTERN_TUPLES_PER_PAGE   4 /* tweak only this */
 
#define EXTERN_TUPLE_MAX_SIZE   MaximumBytesPerTuple(EXTERN_TUPLES_PER_PAGE)
 
#define TOAST_MAX_CHUNK_SIZE
 
#define TOAST_POINTER_SIZE   (VARHDRSZ_EXTERNAL + sizeof(varatt_external))
 
#define INDIRECT_POINTER_SIZE   (VARHDRSZ_EXTERNAL + sizeof(varatt_indirect))
 
#define VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer)   ((toast_pointer).va_extsize < (toast_pointer).va_rawsize - VARHDRSZ)
 
#define VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr)
 

Functions

HeapTuple toast_insert_or_update (Relation rel, HeapTuple newtup, HeapTuple oldtup, int options)
 
void toast_delete (Relation rel, HeapTuple oldtup, bool is_speculative)
 
struct varlenaheap_tuple_fetch_attr (struct varlena *attr)
 
struct varlenaheap_tuple_untoast_attr (struct varlena *attr)
 
struct varlenaheap_tuple_untoast_attr_slice (struct varlena *attr, int32 sliceoffset, int32 slicelength)
 
HeapTuple toast_flatten_tuple (HeapTuple tup, TupleDesc tupleDesc)
 
Datum toast_flatten_tuple_to_datum (HeapTupleHeader tup, uint32 tup_len, TupleDesc tupleDesc)
 
HeapTuple toast_build_flattened_tuple (TupleDesc tupleDesc, Datum *values, bool *isnull)
 
Datum toast_compress_datum (Datum value)
 
Size toast_raw_datum_size (Datum value)
 
Size toast_datum_size (Datum value)
 
Oid toast_get_valid_index (Oid toastoid, LOCKMODE lock)
 

Macro Definition Documentation

◆ EXTERN_TUPLE_MAX_SIZE

#define EXTERN_TUPLE_MAX_SIZE   MaximumBytesPerTuple(EXTERN_TUPLES_PER_PAGE)

Definition at line 89 of file tuptoaster.h.

◆ EXTERN_TUPLES_PER_PAGE

#define EXTERN_TUPLES_PER_PAGE   4 /* tweak only this */

Definition at line 87 of file tuptoaster.h.

◆ INDIRECT_POINTER_SIZE

#define INDIRECT_POINTER_SIZE   (VARHDRSZ_EXTERNAL + sizeof(varatt_indirect))

Definition at line 102 of file tuptoaster.h.

Referenced by make_tuple_indirect(), and ReorderBufferToastReplace().

◆ MaximumBytesPerTuple

#define MaximumBytesPerTuple (   tuplesPerPage)
Value:
MAXALIGN_DOWN((BLCKSZ - \
MAXALIGN(SizeOfPageHeaderData + (tuplesPerPage) * sizeof(ItemIdData))) \
/ (tuplesPerPage))
#define SizeOfPageHeaderData
Definition: bufpage.h:212
#define MAXALIGN(LEN)
Definition: c.h:623
#define MAXALIGN_DOWN(LEN)
Definition: c.h:635

Definition at line 30 of file tuptoaster.h.

◆ TOAST_INDEX_HACK

#define TOAST_INDEX_HACK

Definition at line 24 of file tuptoaster.h.

Referenced by index_form_tuple().

◆ TOAST_INDEX_TARGET

#define TOAST_INDEX_TARGET   (MaxHeapTupleSize / 16)

Definition at line 75 of file tuptoaster.h.

Referenced by gtsvector_compress(), and index_form_tuple().

◆ TOAST_MAX_CHUNK_SIZE

#define TOAST_MAX_CHUNK_SIZE
Value:
MAXALIGN(SizeofHeapTupleHeader) - \
sizeof(Oid) - \
sizeof(int32) - \
VARHDRSZ)
#define SizeofHeapTupleHeader
Definition: htup_details.h:175
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:284
#define EXTERN_TUPLE_MAX_SIZE
Definition: tuptoaster.h:89

Definition at line 91 of file tuptoaster.h.

Referenced by GuessControlValues(), ReadControlFile(), toast_fetch_datum(), toast_fetch_datum_slice(), toast_save_datum(), and WriteControlFile().

◆ TOAST_POINTER_SIZE

#define TOAST_POINTER_SIZE   (VARHDRSZ_EXTERNAL + sizeof(varatt_external))

Definition at line 99 of file tuptoaster.h.

Referenced by toast_insert_or_update(), and toast_save_datum().

◆ TOAST_TUPLE_TARGET

#define TOAST_TUPLE_TARGET   TOAST_TUPLE_THRESHOLD

Definition at line 57 of file tuptoaster.h.

Referenced by toast_insert_or_update().

◆ TOAST_TUPLE_TARGET_MAIN

#define TOAST_TUPLE_TARGET_MAIN   MaximumBytesPerTuple(TOAST_TUPLES_PER_PAGE_MAIN)

Definition at line 68 of file tuptoaster.h.

Referenced by toast_insert_or_update().

◆ TOAST_TUPLE_THRESHOLD

#define TOAST_TUPLE_THRESHOLD   MaximumBytesPerTuple(TOAST_TUPLES_PER_PAGE)

Definition at line 55 of file tuptoaster.h.

Referenced by heap_prepare_insert(), heap_update(), needs_toast_table(), and raw_heap_insert().

◆ TOAST_TUPLES_PER_PAGE

#define TOAST_TUPLES_PER_PAGE   4

Definition at line 53 of file tuptoaster.h.

◆ TOAST_TUPLES_PER_PAGE_MAIN

#define TOAST_TUPLES_PER_PAGE_MAIN   1

Definition at line 66 of file tuptoaster.h.

◆ VARATT_EXTERNAL_GET_POINTER

#define VARATT_EXTERNAL_GET_POINTER (   toast_pointer,
  attr 
)
Value:
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)
#define VARHDRSZ_EXTERNAL
Definition: postgres.h:277
#define VARDATA_EXTERNAL(PTR)
Definition: postgres.h:311
#define VARATT_IS_EXTERNAL(PTR)
Definition: postgres.h:314
#define VARSIZE_EXTERNAL(PTR)
Definition: postgres.h:310

Definition at line 121 of file tuptoaster.h.

Referenced by heap_tuple_fetch_attr(), heap_tuple_untoast_attr(), heap_tuple_untoast_attr_slice(), ReorderBufferToastReplace(), toast_datum_size(), toast_delete_datum(), toast_fetch_datum(), toast_fetch_datum_slice(), toast_raw_datum_size(), and toast_save_datum().

◆ VARATT_EXTERNAL_IS_COMPRESSED

#define VARATT_EXTERNAL_IS_COMPRESSED (   toast_pointer)    ((toast_pointer).va_extsize < (toast_pointer).va_rawsize - VARHDRSZ)

Function Documentation

◆ heap_tuple_fetch_attr()

struct varlena* heap_tuple_fetch_attr ( struct varlena attr)

Definition at line 101 of file tuptoaster.c.

References Assert, DatumGetEOHP(), EOH_flatten_into(), EOH_get_flat_size(), heap_tuple_fetch_attr(), palloc(), varatt_indirect::pointer, PointerGetDatum, toast_fetch_datum(), VARATT_EXTERNAL_GET_POINTER, VARATT_IS_EXTERNAL, VARATT_IS_EXTERNAL_EXPANDED, VARATT_IS_EXTERNAL_INDIRECT, VARATT_IS_EXTERNAL_ONDISK, and VARSIZE_ANY.

Referenced by heap_tuple_fetch_attr(), heap_tuple_untoast_attr(), heap_tuple_untoast_attr_slice(), index_form_tuple(), make_tuple_indirect(), toast_build_flattened_tuple(), toast_flatten_tuple(), toast_insert_or_update(), and tstoreReceiveSlot_detoast().

102 {
103  struct varlena *result;
104 
105  if (VARATT_IS_EXTERNAL_ONDISK(attr))
106  {
107  /*
108  * This is an external stored plain value
109  */
110  result = toast_fetch_datum(attr);
111  }
112  else if (VARATT_IS_EXTERNAL_INDIRECT(attr))
113  {
114  /*
115  * This is an indirect pointer --- dereference it
116  */
117  struct varatt_indirect redirect;
118 
119  VARATT_EXTERNAL_GET_POINTER(redirect, attr);
120  attr = (struct varlena *) redirect.pointer;
121 
122  /* nested indirect Datums aren't allowed */
124 
125  /* recurse if value is still external in some other way */
126  if (VARATT_IS_EXTERNAL(attr))
127  return heap_tuple_fetch_attr(attr);
128 
129  /*
130  * Copy into the caller's memory context, in case caller tries to
131  * pfree the result.
132  */
133  result = (struct varlena *) palloc(VARSIZE_ANY(attr));
134  memcpy(result, attr, VARSIZE_ANY(attr));
135  }
136  else if (VARATT_IS_EXTERNAL_EXPANDED(attr))
137  {
138  /*
139  * This is an expanded-object pointer --- get flat format
140  */
142  Size resultsize;
143 
144  eoh = DatumGetEOHP(PointerGetDatum(attr));
145  resultsize = EOH_get_flat_size(eoh);
146  result = (struct varlena *) palloc(resultsize);
147  EOH_flatten_into(eoh, (void *) result, resultsize);
148  }
149  else
150  {
151  /*
152  * This is a plain value inside of the main tuple - why am I called?
153  */
154  result = attr;
155  }
156 
157  return result;
158 }
#define VARATT_IS_EXTERNAL_ONDISK(PTR)
Definition: postgres.h:315
#define VARATT_IS_EXTERNAL_EXPANDED(PTR)
Definition: postgres.h:323
#define PointerGetDatum(X)
Definition: postgres.h:562
struct varlena * heap_tuple_fetch_attr(struct varlena *attr)
Definition: tuptoaster.c:101
#define VARATT_IS_EXTERNAL(PTR)
Definition: postgres.h:314
#define VARATT_IS_EXTERNAL_INDIRECT(PTR)
Definition: postgres.h:317
Size EOH_get_flat_size(ExpandedObjectHeader *eohptr)
Definition: expandeddatum.c:75
ExpandedObjectHeader * DatumGetEOHP(Datum d)
Definition: expandeddatum.c:29
void EOH_flatten_into(ExpandedObjectHeader *eohptr, void *result, Size allocated_size)
Definition: expandeddatum.c:81
#define VARSIZE_ANY(PTR)
Definition: postgres.h:334
#define Assert(condition)
Definition: c.h:670
#define VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr)
Definition: tuptoaster.h:121
static struct varlena * toast_fetch_datum(struct varlena *attr)
Definition: tuptoaster.c:1874
size_t Size
Definition: c.h:404
void * palloc(Size size)
Definition: mcxt.c:848
Definition: c.h:487

◆ heap_tuple_untoast_attr()

struct varlena* heap_tuple_untoast_attr ( struct varlena attr)

Definition at line 172 of file tuptoaster.c.

References Assert, heap_tuple_fetch_attr(), heap_tuple_untoast_attr(), palloc(), pfree(), varatt_indirect::pointer, SET_VARSIZE, toast_decompress_datum(), toast_fetch_datum(), VARATT_EXTERNAL_GET_POINTER, VARATT_IS_COMPRESSED, VARATT_IS_EXTENDED, VARATT_IS_EXTERNAL_EXPANDED, VARATT_IS_EXTERNAL_INDIRECT, VARATT_IS_EXTERNAL_ONDISK, VARATT_IS_SHORT, VARDATA, VARDATA_SHORT, VARHDRSZ, VARHDRSZ_SHORT, VARSIZE_ANY, and VARSIZE_SHORT.

Referenced by getdatafield(), heap_tuple_untoast_attr(), pg_detoast_datum(), pg_detoast_datum_copy(), pg_detoast_datum_packed(), toast_flatten_tuple_to_datum(), and toast_insert_or_update().

173 {
174  if (VARATT_IS_EXTERNAL_ONDISK(attr))
175  {
176  /*
177  * This is an externally stored datum --- fetch it back from there
178  */
179  attr = toast_fetch_datum(attr);
180  /* If it's compressed, decompress it */
181  if (VARATT_IS_COMPRESSED(attr))
182  {
183  struct varlena *tmp = attr;
184 
185  attr = toast_decompress_datum(tmp);
186  pfree(tmp);
187  }
188  }
189  else if (VARATT_IS_EXTERNAL_INDIRECT(attr))
190  {
191  /*
192  * This is an indirect pointer --- dereference it
193  */
194  struct varatt_indirect redirect;
195 
196  VARATT_EXTERNAL_GET_POINTER(redirect, attr);
197  attr = (struct varlena *) redirect.pointer;
198 
199  /* nested indirect Datums aren't allowed */
201 
202  /* recurse in case value is still extended in some other way */
203  attr = heap_tuple_untoast_attr(attr);
204 
205  /* if it isn't, we'd better copy it */
206  if (attr == (struct varlena *) redirect.pointer)
207  {
208  struct varlena *result;
209 
210  result = (struct varlena *) palloc(VARSIZE_ANY(attr));
211  memcpy(result, attr, VARSIZE_ANY(attr));
212  attr = result;
213  }
214  }
215  else if (VARATT_IS_EXTERNAL_EXPANDED(attr))
216  {
217  /*
218  * This is an expanded-object pointer --- get flat format
219  */
220  attr = heap_tuple_fetch_attr(attr);
221  /* flatteners are not allowed to produce compressed/short output */
222  Assert(!VARATT_IS_EXTENDED(attr));
223  }
224  else if (VARATT_IS_COMPRESSED(attr))
225  {
226  /*
227  * This is a compressed value inside of the main tuple
228  */
229  attr = toast_decompress_datum(attr);
230  }
231  else if (VARATT_IS_SHORT(attr))
232  {
233  /*
234  * This is a short-header varlena --- convert to 4-byte header format
235  */
236  Size data_size = VARSIZE_SHORT(attr) - VARHDRSZ_SHORT;
237  Size new_size = data_size + VARHDRSZ;
238  struct varlena *new_attr;
239 
240  new_attr = (struct varlena *) palloc(new_size);
241  SET_VARSIZE(new_attr, new_size);
242  memcpy(VARDATA(new_attr), VARDATA_SHORT(attr), data_size);
243  attr = new_attr;
244  }
245 
246  return attr;
247 }
#define VARATT_IS_EXTERNAL_ONDISK(PTR)
Definition: postgres.h:315
#define VARATT_IS_COMPRESSED(PTR)
Definition: postgres.h:313
#define VARDATA(PTR)
Definition: postgres.h:303
#define VARATT_IS_EXTERNAL_EXPANDED(PTR)
Definition: postgres.h:323
#define VARHDRSZ_SHORT
Definition: postgres.h:269
struct varlena * heap_tuple_fetch_attr(struct varlena *attr)
Definition: tuptoaster.c:101
#define VARHDRSZ
Definition: c.h:493
struct varlena * heap_tuple_untoast_attr(struct varlena *attr)
Definition: tuptoaster.c:172
void pfree(void *pointer)
Definition: mcxt.c:949
#define VARATT_IS_EXTERNAL_INDIRECT(PTR)
Definition: postgres.h:317
#define VARATT_IS_SHORT(PTR)
Definition: postgres.h:325
#define VARSIZE_SHORT(PTR)
Definition: postgres.h:306
#define VARSIZE_ANY(PTR)
Definition: postgres.h:334
#define Assert(condition)
Definition: c.h:670
#define VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr)
Definition: tuptoaster.h:121
static struct varlena * toast_fetch_datum(struct varlena *attr)
Definition: tuptoaster.c:1874
size_t Size
Definition: c.h:404
static struct varlena * toast_decompress_datum(struct varlena *attr)
Definition: tuptoaster.c:2277
#define VARATT_IS_EXTENDED(PTR)
Definition: postgres.h:326
#define VARDATA_SHORT(PTR)
Definition: postgres.h:307
void * palloc(Size size)
Definition: mcxt.c:848
Definition: c.h:487
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:328

◆ heap_tuple_untoast_attr_slice()

struct varlena* heap_tuple_untoast_attr_slice ( struct varlena attr,
int32  sliceoffset,
int32  slicelength 
)

Definition at line 258 of file tuptoaster.c.

References Assert, heap_tuple_fetch_attr(), heap_tuple_untoast_attr_slice(), palloc(), pfree(), varatt_indirect::pointer, SET_VARSIZE, toast_decompress_datum(), toast_fetch_datum(), toast_fetch_datum_slice(), VARATT_EXTERNAL_GET_POINTER, VARATT_EXTERNAL_IS_COMPRESSED, VARATT_IS_COMPRESSED, VARATT_IS_EXTERNAL, VARATT_IS_EXTERNAL_EXPANDED, VARATT_IS_EXTERNAL_INDIRECT, VARATT_IS_EXTERNAL_ONDISK, VARATT_IS_SHORT, VARDATA, VARDATA_SHORT, VARHDRSZ, VARHDRSZ_SHORT, VARSIZE, and VARSIZE_SHORT.

Referenced by heap_tuple_untoast_attr_slice(), and pg_detoast_datum_slice().

260 {
261  struct varlena *preslice;
262  struct varlena *result;
263  char *attrdata;
264  int32 attrsize;
265 
266  if (VARATT_IS_EXTERNAL_ONDISK(attr))
267  {
268  struct varatt_external toast_pointer;
269 
270  VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
271 
272  /* fast path for non-compressed external datums */
273  if (!VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer))
274  return toast_fetch_datum_slice(attr, sliceoffset, slicelength);
275 
276  /* fetch it back (compressed marker will get set automatically) */
277  preslice = toast_fetch_datum(attr);
278  }
279  else if (VARATT_IS_EXTERNAL_INDIRECT(attr))
280  {
281  struct varatt_indirect redirect;
282 
283  VARATT_EXTERNAL_GET_POINTER(redirect, attr);
284 
285  /* nested indirect Datums aren't allowed */
286  Assert(!VARATT_IS_EXTERNAL_INDIRECT(redirect.pointer));
287 
288  return heap_tuple_untoast_attr_slice(redirect.pointer,
289  sliceoffset, slicelength);
290  }
291  else if (VARATT_IS_EXTERNAL_EXPANDED(attr))
292  {
293  /* pass it off to heap_tuple_fetch_attr to flatten */
294  preslice = heap_tuple_fetch_attr(attr);
295  }
296  else
297  preslice = attr;
298 
299  Assert(!VARATT_IS_EXTERNAL(preslice));
300 
301  if (VARATT_IS_COMPRESSED(preslice))
302  {
303  struct varlena *tmp = preslice;
304 
305  preslice = toast_decompress_datum(tmp);
306 
307  if (tmp != attr)
308  pfree(tmp);
309  }
310 
311  if (VARATT_IS_SHORT(preslice))
312  {
313  attrdata = VARDATA_SHORT(preslice);
314  attrsize = VARSIZE_SHORT(preslice) - VARHDRSZ_SHORT;
315  }
316  else
317  {
318  attrdata = VARDATA(preslice);
319  attrsize = VARSIZE(preslice) - VARHDRSZ;
320  }
321 
322  /* slicing of datum for compressed cases and plain value */
323 
324  if (sliceoffset >= attrsize)
325  {
326  sliceoffset = 0;
327  slicelength = 0;
328  }
329 
330  if (((sliceoffset + slicelength) > attrsize) || slicelength < 0)
331  slicelength = attrsize - sliceoffset;
332 
333  result = (struct varlena *) palloc(slicelength + VARHDRSZ);
334  SET_VARSIZE(result, slicelength + VARHDRSZ);
335 
336  memcpy(VARDATA(result), attrdata + sliceoffset, slicelength);
337 
338  if (preslice != attr)
339  pfree(preslice);
340 
341  return result;
342 }
#define VARATT_IS_EXTERNAL_ONDISK(PTR)
Definition: postgres.h:315
static struct varlena * toast_fetch_datum_slice(struct varlena *attr, int32 sliceoffset, int32 length)
Definition: tuptoaster.c:2045
#define VARATT_IS_COMPRESSED(PTR)
Definition: postgres.h:313
#define VARDATA(PTR)
Definition: postgres.h:303
#define VARATT_IS_EXTERNAL_EXPANDED(PTR)
Definition: postgres.h:323
#define VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer)
Definition: tuptoaster.h:111
#define VARHDRSZ_SHORT
Definition: postgres.h:269
#define VARSIZE(PTR)
Definition: postgres.h:304
struct varlena * heap_tuple_fetch_attr(struct varlena *attr)
Definition: tuptoaster.c:101
#define VARHDRSZ
Definition: c.h:493
signed int int32
Definition: c.h:284
#define VARATT_IS_EXTERNAL(PTR)
Definition: postgres.h:314
void pfree(void *pointer)
Definition: mcxt.c:949
#define VARATT_IS_EXTERNAL_INDIRECT(PTR)
Definition: postgres.h:317
#define VARATT_IS_SHORT(PTR)
Definition: postgres.h:325
#define VARSIZE_SHORT(PTR)
Definition: postgres.h:306
struct varlena * heap_tuple_untoast_attr_slice(struct varlena *attr, int32 sliceoffset, int32 slicelength)
Definition: tuptoaster.c:258
#define Assert(condition)
Definition: c.h:670
#define VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr)
Definition: tuptoaster.h:121
static struct varlena * toast_fetch_datum(struct varlena *attr)
Definition: tuptoaster.c:1874
static struct varlena * toast_decompress_datum(struct varlena *attr)
Definition: tuptoaster.c:2277
#define VARDATA_SHORT(PTR)
Definition: postgres.h:307
void * palloc(Size size)
Definition: mcxt.c:848
Definition: c.h:487
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:328

◆ toast_build_flattened_tuple()

HeapTuple toast_build_flattened_tuple ( TupleDesc  tupleDesc,
Datum values,
bool isnull 
)

Definition at line 1304 of file tuptoaster.c.

References Assert, DatumGetPointer, heap_form_tuple(), heap_tuple_fetch_attr(), i, MaxTupleAttributeNumber, tupleDesc::natts, pfree(), PointerGetDatum, TupleDescAttr, and VARATT_IS_EXTERNAL.

Referenced by ExecEvalWholeRowVar().

1307 {
1308  HeapTuple new_tuple;
1309  int numAttrs = tupleDesc->natts;
1310  int num_to_free;
1311  int i;
1312  Datum new_values[MaxTupleAttributeNumber];
1313  Pointer freeable_values[MaxTupleAttributeNumber];
1314 
1315  /*
1316  * We can pass the caller's isnull array directly to heap_form_tuple, but
1317  * we potentially need to modify the values array.
1318  */
1319  Assert(numAttrs <= MaxTupleAttributeNumber);
1320  memcpy(new_values, values, numAttrs * sizeof(Datum));
1321 
1322  num_to_free = 0;
1323  for (i = 0; i < numAttrs; i++)
1324  {
1325  /*
1326  * Look at non-null varlena attributes
1327  */
1328  if (!isnull[i] && TupleDescAttr(tupleDesc, i)->attlen == -1)
1329  {
1330  struct varlena *new_value;
1331 
1332  new_value = (struct varlena *) DatumGetPointer(new_values[i]);
1333  if (VARATT_IS_EXTERNAL(new_value))
1334  {
1335  new_value = heap_tuple_fetch_attr(new_value);
1336  new_values[i] = PointerGetDatum(new_value);
1337  freeable_values[num_to_free++] = (Pointer) new_value;
1338  }
1339  }
1340  }
1341 
1342  /*
1343  * Form the reconfigured tuple.
1344  */
1345  new_tuple = heap_form_tuple(tupleDesc, new_values, isnull);
1346 
1347  /*
1348  * Free allocated temp values
1349  */
1350  for (i = 0; i < num_to_free; i++)
1351  pfree(freeable_values[i]);
1352 
1353  return new_tuple;
1354 }
#define MaxTupleAttributeNumber
Definition: htup_details.h:33
#define PointerGetDatum(X)
Definition: postgres.h:562
struct varlena * heap_tuple_fetch_attr(struct varlena *attr)
Definition: tuptoaster.c:101
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:695
int natts
Definition: tupdesc.h:79
#define VARATT_IS_EXTERNAL(PTR)
Definition: postgres.h:314
void pfree(void *pointer)
Definition: mcxt.c:949
char * Pointer
Definition: c.h:273
uintptr_t Datum
Definition: postgres.h:372
#define Assert(condition)
Definition: c.h:670
#define DatumGetPointer(X)
Definition: postgres.h:555
static Datum values[MAXATTR]
Definition: bootstrap.c:164
int i
Definition: c.h:487

◆ toast_compress_datum()

Datum toast_compress_datum ( Datum  value)

Definition at line 1371 of file tuptoaster.c.

References Assert, DatumGetPointer, PGLZ_Strategy::max_input_size, palloc(), pfree(), pglz_compress(), PGLZ_MAX_OUTPUT, PGLZ_strategy_default, PointerGetDatum, SET_VARSIZE_COMPRESSED, TOAST_COMPRESS_HDRSZ, TOAST_COMPRESS_RAWDATA, TOAST_COMPRESS_SET_RAWSIZE, VARATT_IS_COMPRESSED, VARATT_IS_EXTERNAL, VARDATA_ANY, and VARSIZE_ANY_EXHDR.

Referenced by index_form_tuple(), and toast_insert_or_update().

1372 {
1373  struct varlena *tmp;
1375  int32 len;
1376 
1379 
1380  /*
1381  * No point in wasting a palloc cycle if value size is out of the allowed
1382  * range for compression
1383  */
1384  if (valsize < PGLZ_strategy_default->min_input_size ||
1386  return PointerGetDatum(NULL);
1387 
1388  tmp = (struct varlena *) palloc(PGLZ_MAX_OUTPUT(valsize) +
1390 
1391  /*
1392  * We recheck the actual size even if pglz_compress() reports success,
1393  * because it might be satisfied with having saved as little as one byte
1394  * in the compressed data --- which could turn into a net loss once you
1395  * consider header and alignment padding. Worst case, the compressed
1396  * format might require three padding bytes (plus header, which is
1397  * included in VARSIZE(tmp)), whereas the uncompressed format would take
1398  * only one header byte and no padding if the value is short enough. So
1399  * we insist on a savings of more than 2 bytes to ensure we have a gain.
1400  */
1402  valsize,
1405  if (len >= 0 &&
1406  len + TOAST_COMPRESS_HDRSZ < valsize - 2)
1407  {
1408  TOAST_COMPRESS_SET_RAWSIZE(tmp, valsize);
1410  /* successful compression */
1411  return PointerGetDatum(tmp);
1412  }
1413  else
1414  {
1415  /* incompressible data */
1416  pfree(tmp);
1417  return PointerGetDatum(NULL);
1418  }
1419 }
#define VARATT_IS_COMPRESSED(PTR)
Definition: postgres.h:313
#define VARDATA_ANY(PTR)
Definition: postgres.h:347
#define TOAST_COMPRESS_HDRSZ
Definition: tuptoaster.c:63
#define PointerGetDatum(X)
Definition: postgres.h:562
signed int int32
Definition: c.h:284
#define TOAST_COMPRESS_SET_RAWSIZE(ptr, len)
Definition: tuptoaster.c:67
#define VARATT_IS_EXTERNAL(PTR)
Definition: postgres.h:314
void pfree(void *pointer)
Definition: mcxt.c:949
static struct @121 value
int32 pglz_compress(const char *source, int32 slen, char *dest, const PGLZ_Strategy *strategy)
#define PGLZ_MAX_OUTPUT(_dlen)
Definition: pg_lzcompress.h:21
#define Assert(condition)
Definition: c.h:670
int32 max_input_size
Definition: pg_lzcompress.h:60
#define DatumGetPointer(X)
Definition: postgres.h:555
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:340
void * palloc(Size size)
Definition: mcxt.c:848
#define TOAST_COMPRESS_RAWDATA(ptr)
Definition: tuptoaster.c:65
#define SET_VARSIZE_COMPRESSED(PTR, len)
Definition: postgres.h:330
Definition: c.h:487
const PGLZ_Strategy *const PGLZ_strategy_default

◆ toast_datum_size()

Size toast_datum_size ( Datum  value)

Definition at line 409 of file tuptoaster.c.

References Assert, DatumGetEOHP(), DatumGetPointer, EOH_get_flat_size(), varatt_indirect::pointer, PointerGetDatum, toast_datum_size(), varatt_external::va_extsize, VARATT_EXTERNAL_GET_POINTER, VARATT_IS_EXTERNAL_EXPANDED, VARATT_IS_EXTERNAL_INDIRECT, VARATT_IS_EXTERNAL_ONDISK, VARATT_IS_SHORT, VARSIZE, and VARSIZE_SHORT.

Referenced by pg_column_size(), and toast_datum_size().

410 {
411  struct varlena *attr = (struct varlena *) DatumGetPointer(value);
412  Size result;
413 
414  if (VARATT_IS_EXTERNAL_ONDISK(attr))
415  {
416  /*
417  * Attribute is stored externally - return the extsize whether
418  * compressed or not. We do not count the size of the toast pointer
419  * ... should we?
420  */
421  struct varatt_external toast_pointer;
422 
423  VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
424  result = toast_pointer.va_extsize;
425  }
426  else if (VARATT_IS_EXTERNAL_INDIRECT(attr))
427  {
428  struct varatt_indirect toast_pointer;
429 
430  VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
431 
432  /* nested indirect Datums aren't allowed */
434 
435  return toast_datum_size(PointerGetDatum(toast_pointer.pointer));
436  }
437  else if (VARATT_IS_EXTERNAL_EXPANDED(attr))
438  {
440  }
441  else if (VARATT_IS_SHORT(attr))
442  {
443  result = VARSIZE_SHORT(attr);
444  }
445  else
446  {
447  /*
448  * Attribute is stored inline either compressed or not, just calculate
449  * the size of the datum in either case.
450  */
451  result = VARSIZE(attr);
452  }
453  return result;
454 }
#define VARATT_IS_EXTERNAL_ONDISK(PTR)
Definition: postgres.h:315
#define VARATT_IS_EXTERNAL_EXPANDED(PTR)
Definition: postgres.h:323
#define VARSIZE(PTR)
Definition: postgres.h:304
#define PointerGetDatum(X)
Definition: postgres.h:562
#define VARATT_IS_EXTERNAL_INDIRECT(PTR)
Definition: postgres.h:317
#define VARATT_IS_SHORT(PTR)
Definition: postgres.h:325
Size toast_datum_size(Datum value)
Definition: tuptoaster.c:409
static struct @121 value
Size EOH_get_flat_size(ExpandedObjectHeader *eohptr)
Definition: expandeddatum.c:75
#define VARSIZE_SHORT(PTR)
Definition: postgres.h:306
ExpandedObjectHeader * DatumGetEOHP(Datum d)
Definition: expandeddatum.c:29
#define Assert(condition)
Definition: c.h:670
#define VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr)
Definition: tuptoaster.h:121
size_t Size
Definition: c.h:404
#define DatumGetPointer(X)
Definition: postgres.h:555
Definition: c.h:487

◆ toast_delete()

void toast_delete ( Relation  rel,
HeapTuple  oldtup,
bool  is_speculative 
)

Definition at line 464 of file tuptoaster.c.

References Assert, heap_deform_tuple(), i, MaxHeapAttributeNumber, tupleDesc::natts, PointerGetDatum, RelationData::rd_att, RelationData::rd_rel, RELKIND_MATVIEW, RELKIND_RELATION, toast_delete_datum(), TupleDescAttr, value, and VARATT_IS_EXTERNAL_ONDISK.

Referenced by heap_abort_speculative(), and heap_delete().

465 {
467  int numAttrs;
468  int i;
469  Datum toast_values[MaxHeapAttributeNumber];
470  bool toast_isnull[MaxHeapAttributeNumber];
471 
472  /*
473  * We should only ever be called for tuples of plain relations or
474  * materialized views --- recursing on a toast rel is bad news.
475  */
476  Assert(rel->rd_rel->relkind == RELKIND_RELATION ||
477  rel->rd_rel->relkind == RELKIND_MATVIEW);
478 
479  /*
480  * Get the tuple descriptor and break down the tuple into fields.
481  *
482  * NOTE: it's debatable whether to use heap_deform_tuple() here or just
483  * heap_getattr() only the varlena columns. The latter could win if there
484  * are few varlena columns and many non-varlena ones. However,
485  * heap_deform_tuple costs only O(N) while the heap_getattr way would cost
486  * O(N^2) if there are many varlena columns, so it seems better to err on
487  * the side of linear cost. (We won't even be here unless there's at
488  * least one varlena column, by the way.)
489  */
490  tupleDesc = rel->rd_att;
491  numAttrs = tupleDesc->natts;
492 
493  Assert(numAttrs <= MaxHeapAttributeNumber);
494  heap_deform_tuple(oldtup, tupleDesc, toast_values, toast_isnull);
495 
496  /*
497  * Check for external stored attributes and delete them from the secondary
498  * relation.
499  */
500  for (i = 0; i < numAttrs; i++)
501  {
502  if (TupleDescAttr(tupleDesc, i)->attlen == -1)
503  {
504  Datum value = toast_values[i];
505 
506  if (toast_isnull[i])
507  continue;
509  toast_delete_datum(rel, value, is_speculative);
510  }
511  }
512 }
#define VARATT_IS_EXTERNAL_ONDISK(PTR)
Definition: postgres.h:315
#define PointerGetDatum(X)
Definition: postgres.h:562
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
#define RELKIND_MATVIEW
Definition: pg_class.h:165
Form_pg_class rd_rel
Definition: rel.h:114
int natts
Definition: tupdesc.h:79
static struct @121 value
uintptr_t Datum
Definition: postgres.h:372
TupleDesc rd_att
Definition: rel.h:115
#define MaxHeapAttributeNumber
Definition: htup_details.h:47
#define Assert(condition)
Definition: c.h:670
void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)
Definition: heaptuple.c:936
static void toast_delete_datum(Relation rel, Datum value, bool is_speculative)
Definition: tuptoaster.c:1728
int i
#define RELKIND_RELATION
Definition: pg_class.h:160

◆ toast_flatten_tuple()

HeapTuple toast_flatten_tuple ( HeapTuple  tup,
TupleDesc  tupleDesc 
)

Definition at line 1085 of file tuptoaster.c.

References Assert, DatumGetPointer, HEAP2_XACT_MASK, heap_deform_tuple(), heap_form_tuple(), heap_tuple_fetch_attr(), HEAP_XACT_MASK, HeapTupleGetOid, HeapTupleSetOid, i, MaxTupleAttributeNumber, tupleDesc::natts, pfree(), PointerGetDatum, HeapTupleHeaderData::t_choice, HeapTupleHeaderData::t_ctid, HeapTupleData::t_data, HeapTupleHeaderData::t_infomask, HeapTupleHeaderData::t_infomask2, HeapTupleData::t_self, HeapTupleData::t_tableOid, tupleDesc::tdhasoid, TupleDescAttr, and VARATT_IS_EXTERNAL.

Referenced by CatalogCacheCreateEntry(), and ExtractReplicaIdentity().

1086 {
1087  HeapTuple new_tuple;
1088  int numAttrs = tupleDesc->natts;
1089  int i;
1090  Datum toast_values[MaxTupleAttributeNumber];
1091  bool toast_isnull[MaxTupleAttributeNumber];
1092  bool toast_free[MaxTupleAttributeNumber];
1093 
1094  /*
1095  * Break down the tuple into fields.
1096  */
1097  Assert(numAttrs <= MaxTupleAttributeNumber);
1098  heap_deform_tuple(tup, tupleDesc, toast_values, toast_isnull);
1099 
1100  memset(toast_free, 0, numAttrs * sizeof(bool));
1101 
1102  for (i = 0; i < numAttrs; i++)
1103  {
1104  /*
1105  * Look at non-null varlena attributes
1106  */
1107  if (!toast_isnull[i] && TupleDescAttr(tupleDesc, i)->attlen == -1)
1108  {
1109  struct varlena *new_value;
1110 
1111  new_value = (struct varlena *) DatumGetPointer(toast_values[i]);
1112  if (VARATT_IS_EXTERNAL(new_value))
1113  {
1114  new_value = heap_tuple_fetch_attr(new_value);
1115  toast_values[i] = PointerGetDatum(new_value);
1116  toast_free[i] = true;
1117  }
1118  }
1119  }
1120 
1121  /*
1122  * Form the reconfigured tuple.
1123  */
1124  new_tuple = heap_form_tuple(tupleDesc, toast_values, toast_isnull);
1125 
1126  /*
1127  * Be sure to copy the tuple's OID and identity fields. We also make a
1128  * point of copying visibility info, just in case anybody looks at those
1129  * fields in a syscache entry.
1130  */
1131  if (tupleDesc->tdhasoid)
1132  HeapTupleSetOid(new_tuple, HeapTupleGetOid(tup));
1133 
1134  new_tuple->t_self = tup->t_self;
1135  new_tuple->t_tableOid = tup->t_tableOid;
1136 
1137  new_tuple->t_data->t_choice = tup->t_data->t_choice;
1138  new_tuple->t_data->t_ctid = tup->t_data->t_ctid;
1139  new_tuple->t_data->t_infomask &= ~HEAP_XACT_MASK;
1140  new_tuple->t_data->t_infomask |=
1142  new_tuple->t_data->t_infomask2 &= ~HEAP2_XACT_MASK;
1143  new_tuple->t_data->t_infomask2 |=
1145 
1146  /*
1147  * Free allocated temp values
1148  */
1149  for (i = 0; i < numAttrs; i++)
1150  if (toast_free[i])
1151  pfree(DatumGetPointer(toast_values[i]));
1152 
1153  return new_tuple;
1154 }
union HeapTupleHeaderData::@45 t_choice
bool tdhasoid
Definition: tupdesc.h:82
#define MaxTupleAttributeNumber
Definition: htup_details.h:33
#define PointerGetDatum(X)
Definition: postgres.h:562
struct varlena * heap_tuple_fetch_attr(struct varlena *attr)
Definition: tuptoaster.c:101
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
#define HEAP2_XACT_MASK
Definition: htup_details.h:274
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:695
int natts
Definition: tupdesc.h:79
HeapTupleHeader t_data
Definition: htup.h:67
#define HeapTupleSetOid(tuple, oid)
Definition: htup_details.h:703
#define VARATT_IS_EXTERNAL(PTR)
Definition: postgres.h:314
void pfree(void *pointer)
Definition: mcxt.c:949
ItemPointerData t_ctid
Definition: htup_details.h:155
ItemPointerData t_self
Definition: htup.h:65
Oid t_tableOid
Definition: htup.h:66
uintptr_t Datum
Definition: postgres.h:372
#define Assert(condition)
Definition: c.h:670
#define DatumGetPointer(X)
Definition: postgres.h:555
void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)
Definition: heaptuple.c:936
int i
Definition: c.h:487
#define HEAP_XACT_MASK
Definition: htup_details.h:209
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700

◆ toast_flatten_tuple_to_datum()

Datum toast_flatten_tuple_to_datum ( HeapTupleHeader  tup,
uint32  tup_len,
TupleDesc  tupleDesc 
)

Definition at line 1187 of file tuptoaster.c.

References Assert, BITMAPLEN, DatumGetPointer, heap_compute_data_size(), heap_deform_tuple(), heap_fill_tuple(), HEAP_HASOID, heap_tuple_untoast_attr(), HeapTupleHeaderGetOid, HeapTupleHeaderSetDatumLength, HeapTupleHeaderSetNatts, HeapTupleHeaderSetOid, HeapTupleHeaderSetTypeId, HeapTupleHeaderSetTypMod, i, InvalidOid, ItemPointerSetInvalid, MAXALIGN, MaxTupleAttributeNumber, tupleDesc::natts, palloc0(), pfree(), PointerGetDatum, SizeofHeapTupleHeader, HeapTupleHeaderData::t_bits, HeapTupleData::t_data, HeapTupleHeaderData::t_hoff, HeapTupleHeaderData::t_infomask, HeapTupleData::t_len, HeapTupleData::t_self, HeapTupleData::t_tableOid, tupleDesc::tdtypeid, tupleDesc::tdtypmod, TupleDescAttr, VARATT_IS_COMPRESSED, and VARATT_IS_EXTERNAL.

Referenced by heap_copy_tuple_as_datum(), and HeapTupleHeaderGetDatum().

1190 {
1191  HeapTupleHeader new_data;
1192  int32 new_header_len;
1193  int32 new_data_len;
1194  int32 new_tuple_len;
1195  HeapTupleData tmptup;
1196  int numAttrs = tupleDesc->natts;
1197  int i;
1198  bool has_nulls = false;
1199  Datum toast_values[MaxTupleAttributeNumber];
1200  bool toast_isnull[MaxTupleAttributeNumber];
1201  bool toast_free[MaxTupleAttributeNumber];
1202 
1203  /* Build a temporary HeapTuple control structure */
1204  tmptup.t_len = tup_len;
1205  ItemPointerSetInvalid(&(tmptup.t_self));
1206  tmptup.t_tableOid = InvalidOid;
1207  tmptup.t_data = tup;
1208 
1209  /*
1210  * Break down the tuple into fields.
1211  */
1212  Assert(numAttrs <= MaxTupleAttributeNumber);
1213  heap_deform_tuple(&tmptup, tupleDesc, toast_values, toast_isnull);
1214 
1215  memset(toast_free, 0, numAttrs * sizeof(bool));
1216 
1217  for (i = 0; i < numAttrs; i++)
1218  {
1219  /*
1220  * Look at non-null varlena attributes
1221  */
1222  if (toast_isnull[i])
1223  has_nulls = true;
1224  else if (TupleDescAttr(tupleDesc, i)->attlen == -1)
1225  {
1226  struct varlena *new_value;
1227 
1228  new_value = (struct varlena *) DatumGetPointer(toast_values[i]);
1229  if (VARATT_IS_EXTERNAL(new_value) ||
1230  VARATT_IS_COMPRESSED(new_value))
1231  {
1232  new_value = heap_tuple_untoast_attr(new_value);
1233  toast_values[i] = PointerGetDatum(new_value);
1234  toast_free[i] = true;
1235  }
1236  }
1237  }
1238 
1239  /*
1240  * Calculate the new size of the tuple.
1241  *
1242  * This should match the reconstruction code in toast_insert_or_update.
1243  */
1244  new_header_len = SizeofHeapTupleHeader;
1245  if (has_nulls)
1246  new_header_len += BITMAPLEN(numAttrs);
1247  if (tup->t_infomask & HEAP_HASOID)
1248  new_header_len += sizeof(Oid);
1249  new_header_len = MAXALIGN(new_header_len);
1250  new_data_len = heap_compute_data_size(tupleDesc,
1251  toast_values, toast_isnull);
1252  new_tuple_len = new_header_len + new_data_len;
1253 
1254  new_data = (HeapTupleHeader) palloc0(new_tuple_len);
1255 
1256  /*
1257  * Copy the existing tuple header, but adjust natts and t_hoff.
1258  */
1259  memcpy(new_data, tup, SizeofHeapTupleHeader);
1260  HeapTupleHeaderSetNatts(new_data, numAttrs);
1261  new_data->t_hoff = new_header_len;
1262  if (tup->t_infomask & HEAP_HASOID)
1264 
1265  /* Set the composite-Datum header fields correctly */
1266  HeapTupleHeaderSetDatumLength(new_data, new_tuple_len);
1267  HeapTupleHeaderSetTypeId(new_data, tupleDesc->tdtypeid);
1268  HeapTupleHeaderSetTypMod(new_data, tupleDesc->tdtypmod);
1269 
1270  /* Copy over the data, and fill the null bitmap if needed */
1271  heap_fill_tuple(tupleDesc,
1272  toast_values,
1273  toast_isnull,
1274  (char *) new_data + new_header_len,
1275  new_data_len,
1276  &(new_data->t_infomask),
1277  has_nulls ? new_data->t_bits : NULL);
1278 
1279  /*
1280  * Free allocated temp values
1281  */
1282  for (i = 0; i < numAttrs; i++)
1283  if (toast_free[i])
1284  pfree(DatumGetPointer(toast_values[i]));
1285 
1286  return PointerGetDatum(new_data);
1287 }
#define VARATT_IS_COMPRESSED(PTR)
Definition: postgres.h:313
void heap_fill_tuple(TupleDesc tupleDesc, Datum *values, bool *isnull, char *data, Size data_size, uint16 *infomask, bits8 *bit)
Definition: heaptuple.c:145
#define SizeofHeapTupleHeader
Definition: htup_details.h:175
Oid tdtypeid
Definition: tupdesc.h:80
#define HeapTupleHeaderSetTypeId(tup, typeid)
Definition: htup_details.h:455
bits8 t_bits[FLEXIBLE_ARRAY_MEMBER]
Definition: htup_details.h:168
#define MaxTupleAttributeNumber
Definition: htup_details.h:33
#define PointerGetDatum(X)
Definition: postgres.h:562
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
#define BITMAPLEN(NATTS)
Definition: htup_details.h:553
struct varlena * heap_tuple_untoast_attr(struct varlena *attr)
Definition: tuptoaster.c:172
unsigned int Oid
Definition: postgres_ext.h:31
int natts
Definition: tupdesc.h:79
int32 tdtypmod
Definition: tupdesc.h:81
signed int int32
Definition: c.h:284
#define HeapTupleHeaderSetDatumLength(tup, len)
Definition: htup_details.h:447
HeapTupleHeader t_data
Definition: htup.h:67
#define VARATT_IS_EXTERNAL(PTR)
Definition: postgres.h:314
void pfree(void *pointer)
Definition: mcxt.c:949
#define HeapTupleHeaderSetOid(tup, oid)
Definition: htup_details.h:478
ItemPointerData t_self
Definition: htup.h:65
uint32 t_len
Definition: htup.h:64
Oid t_tableOid
Definition: htup.h:66
void * palloc0(Size size)
Definition: mcxt.c:877
uintptr_t Datum
Definition: postgres.h:372
#define HeapTupleHeaderSetTypMod(tup, typmod)
Definition: htup_details.h:465
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:670
#define HeapTupleHeaderSetNatts(tup, natts)
Definition: htup_details.h:540
#define MAXALIGN(LEN)
Definition: c.h:623
Size heap_compute_data_size(TupleDesc tupleDesc, Datum *values, bool *isnull)
Definition: heaptuple.c:85
#define DatumGetPointer(X)
Definition: postgres.h:555
void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)
Definition: heaptuple.c:936
#define HeapTupleHeaderGetOid(tup)
Definition: htup_details.h:470
#define ItemPointerSetInvalid(pointer)
Definition: itemptr.h:150
int i
#define HEAP_HASOID
Definition: htup_details.h:183
Definition: c.h:487

◆ toast_get_valid_index()

Oid toast_get_valid_index ( Oid  toastoid,
LOCKMODE  lock 
)

Definition at line 1429 of file tuptoaster.c.

References heap_close, heap_open(), RelationGetRelid, toast_close_indexes(), and toast_open_indexes().

Referenced by finish_heap_swap(), and swap_relation_files().

1430 {
1431  int num_indexes;
1432  int validIndex;
1433  Oid validIndexOid;
1434  Relation *toastidxs;
1435  Relation toastrel;
1436 
1437  /* Open the toast relation */
1438  toastrel = heap_open(toastoid, lock);
1439 
1440  /* Look for the valid index of the toast relation */
1441  validIndex = toast_open_indexes(toastrel,
1442  lock,
1443  &toastidxs,
1444  &num_indexes);
1445  validIndexOid = RelationGetRelid(toastidxs[validIndex]);
1446 
1447  /* Close the toast relation and all its indexes */
1448  toast_close_indexes(toastidxs, num_indexes, lock);
1449  heap_close(toastrel, lock);
1450 
1451  return validIndexOid;
1452 }
static int toast_open_indexes(Relation toastrel, LOCKMODE lock, Relation **toastidxs, int *num_indexes)
Definition: tuptoaster.c:2306
static void toast_close_indexes(Relation *toastidxs, int num_indexes, LOCKMODE lock)
Definition: tuptoaster.c:2365
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define RelationGetRelid(relation)
Definition: rel.h:425

◆ toast_insert_or_update()

HeapTuple toast_insert_or_update ( Relation  rel,
HeapTuple  newtup,
HeapTuple  oldtup,
int  options 
)

Definition at line 534 of file tuptoaster.c.

References Assert, BITMAPLEN, DatumGetPointer, heap_compute_data_size(), heap_deform_tuple(), heap_fill_tuple(), HEAP_HASOID, HEAP_INSERT_SPECULATIVE, heap_tuple_fetch_attr(), heap_tuple_untoast_attr(), HeapTupleHeaderGetOid, HeapTupleHeaderSetNatts, HeapTupleHeaderSetOid, HEAPTUPLESIZE, i, InvalidOid, MAXALIGN, MaxHeapAttributeNumber, tupleDesc::natts, palloc0(), pfree(), PointerGetDatum, RelationData::rd_att, RelationData::rd_rel, RelationGetToastTupleTarget, RELKIND_MATVIEW, RELKIND_RELATION, SizeofHeapTupleHeader, HeapTupleHeaderData::t_bits, HeapTupleData::t_data, HeapTupleHeaderData::t_hoff, HeapTupleHeaderData::t_infomask, HeapTupleData::t_len, HeapTupleData::t_self, HeapTupleData::t_tableOid, toast_compress_datum(), toast_delete_datum(), TOAST_POINTER_SIZE, toast_save_datum(), TOAST_TUPLE_TARGET, TOAST_TUPLE_TARGET_MAIN, TupleDescAttr, VARATT_IS_COMPRESSED, VARATT_IS_EXTERNAL, VARATT_IS_EXTERNAL_ONDISK, VARSIZE, VARSIZE_ANY, and VARSIZE_EXTERNAL.

Referenced by heap_prepare_insert(), heap_update(), and raw_heap_insert().

536 {
537  HeapTuple result_tuple;
539  int numAttrs;
540  int i;
541 
542  bool need_change = false;
543  bool need_free = false;
544  bool need_delold = false;
545  bool has_nulls = false;
546 
547  Size maxDataLen;
548  Size hoff;
549 
550  char toast_action[MaxHeapAttributeNumber];
551  bool toast_isnull[MaxHeapAttributeNumber];
552  bool toast_oldisnull[MaxHeapAttributeNumber];
553  Datum toast_values[MaxHeapAttributeNumber];
554  Datum toast_oldvalues[MaxHeapAttributeNumber];
555  struct varlena *toast_oldexternal[MaxHeapAttributeNumber];
556  int32 toast_sizes[MaxHeapAttributeNumber];
557  bool toast_free[MaxHeapAttributeNumber];
558  bool toast_delold[MaxHeapAttributeNumber];
559 
560  /*
561  * Ignore the INSERT_SPECULATIVE option. Speculative insertions/super
562  * deletions just normally insert/delete the toast values. It seems
563  * easiest to deal with that here, instead on, potentially, multiple
564  * callers.
565  */
567 
568  /*
569  * We should only ever be called for tuples of plain relations or
570  * materialized views --- recursing on a toast rel is bad news.
571  */
572  Assert(rel->rd_rel->relkind == RELKIND_RELATION ||
573  rel->rd_rel->relkind == RELKIND_MATVIEW);
574 
575  /*
576  * Get the tuple descriptor and break down the tuple(s) into fields.
577  */
578  tupleDesc = rel->rd_att;
579  numAttrs = tupleDesc->natts;
580 
581  Assert(numAttrs <= MaxHeapAttributeNumber);
582  heap_deform_tuple(newtup, tupleDesc, toast_values, toast_isnull);
583  if (oldtup != NULL)
584  heap_deform_tuple(oldtup, tupleDesc, toast_oldvalues, toast_oldisnull);
585 
586  /* ----------
587  * Then collect information about the values given
588  *
589  * NOTE: toast_action[i] can have these values:
590  * ' ' default handling
591  * 'p' already processed --- don't touch it
592  * 'x' incompressible, but OK to move off
593  *
594  * NOTE: toast_sizes[i] is only made valid for varlena attributes with
595  * toast_action[i] different from 'p'.
596  * ----------
597  */
598  memset(toast_action, ' ', numAttrs * sizeof(char));
599  memset(toast_oldexternal, 0, numAttrs * sizeof(struct varlena *));
600  memset(toast_free, 0, numAttrs * sizeof(bool));
601  memset(toast_delold, 0, numAttrs * sizeof(bool));
602 
603  for (i = 0; i < numAttrs; i++)
604  {
605  Form_pg_attribute att = TupleDescAttr(tupleDesc, i);
606  struct varlena *old_value;
607  struct varlena *new_value;
608 
609  if (oldtup != NULL)
610  {
611  /*
612  * For UPDATE get the old and new values of this attribute
613  */
614  old_value = (struct varlena *) DatumGetPointer(toast_oldvalues[i]);
615  new_value = (struct varlena *) DatumGetPointer(toast_values[i]);
616 
617  /*
618  * If the old value is stored on disk, check if it has changed so
619  * we have to delete it later.
620  */
621  if (att->attlen == -1 && !toast_oldisnull[i] &&
622  VARATT_IS_EXTERNAL_ONDISK(old_value))
623  {
624  if (toast_isnull[i] || !VARATT_IS_EXTERNAL_ONDISK(new_value) ||
625  memcmp((char *) old_value, (char *) new_value,
626  VARSIZE_EXTERNAL(old_value)) != 0)
627  {
628  /*
629  * The old external stored value isn't needed any more
630  * after the update
631  */
632  toast_delold[i] = true;
633  need_delold = true;
634  }
635  else
636  {
637  /*
638  * This attribute isn't changed by this update so we reuse
639  * the original reference to the old value in the new
640  * tuple.
641  */
642  toast_action[i] = 'p';
643  continue;
644  }
645  }
646  }
647  else
648  {
649  /*
650  * For INSERT simply get the new value
651  */
652  new_value = (struct varlena *) DatumGetPointer(toast_values[i]);
653  }
654 
655  /*
656  * Handle NULL attributes
657  */
658  if (toast_isnull[i])
659  {
660  toast_action[i] = 'p';
661  has_nulls = true;
662  continue;
663  }
664 
665  /*
666  * Now look at varlena attributes
667  */
668  if (att->attlen == -1)
669  {
670  /*
671  * If the table's attribute says PLAIN always, force it so.
672  */
673  if (att->attstorage == 'p')
674  toast_action[i] = 'p';
675 
676  /*
677  * We took care of UPDATE above, so any external value we find
678  * still in the tuple must be someone else's that we cannot reuse
679  * (this includes the case of an out-of-line in-memory datum).
680  * Fetch it back (without decompression, unless we are forcing
681  * PLAIN storage). If necessary, we'll push it out as a new
682  * external value below.
683  */
684  if (VARATT_IS_EXTERNAL(new_value))
685  {
686  toast_oldexternal[i] = new_value;
687  if (att->attstorage == 'p')
688  new_value = heap_tuple_untoast_attr(new_value);
689  else
690  new_value = heap_tuple_fetch_attr(new_value);
691  toast_values[i] = PointerGetDatum(new_value);
692  toast_free[i] = true;
693  need_change = true;
694  need_free = true;
695  }
696 
697  /*
698  * Remember the size of this attribute
699  */
700  toast_sizes[i] = VARSIZE_ANY(new_value);
701  }
702  else
703  {
704  /*
705  * Not a varlena attribute, plain storage always
706  */
707  toast_action[i] = 'p';
708  }
709  }
710 
711  /* ----------
712  * Compress and/or save external until data fits into target length
713  *
714  * 1: Inline compress attributes with attstorage 'x', and store very
715  * large attributes with attstorage 'x' or 'e' external immediately
716  * 2: Store attributes with attstorage 'x' or 'e' external
717  * 3: Inline compress attributes with attstorage 'm'
718  * 4: Store attributes with attstorage 'm' external
719  * ----------
720  */
721 
722  /* compute header overhead --- this should match heap_form_tuple() */
723  hoff = SizeofHeapTupleHeader;
724  if (has_nulls)
725  hoff += BITMAPLEN(numAttrs);
726  if (newtup->t_data->t_infomask & HEAP_HASOID)
727  hoff += sizeof(Oid);
728  hoff = MAXALIGN(hoff);
729  /* now convert to a limit on the tuple data size */
730  maxDataLen = RelationGetToastTupleTarget(rel, TOAST_TUPLE_TARGET) - hoff;
731 
732  /*
733  * Look for attributes with attstorage 'x' to compress. Also find large
734  * attributes with attstorage 'x' or 'e', and store them external.
735  */
736  while (heap_compute_data_size(tupleDesc,
737  toast_values, toast_isnull) > maxDataLen)
738  {
739  int biggest_attno = -1;
740  int32 biggest_size = MAXALIGN(TOAST_POINTER_SIZE);
741  Datum old_value;
742  Datum new_value;
743 
744  /*
745  * Search for the biggest yet unprocessed internal attribute
746  */
747  for (i = 0; i < numAttrs; i++)
748  {
749  Form_pg_attribute att = TupleDescAttr(tupleDesc, i);
750 
751  if (toast_action[i] != ' ')
752  continue;
753  if (VARATT_IS_EXTERNAL(DatumGetPointer(toast_values[i])))
754  continue; /* can't happen, toast_action would be 'p' */
755  if (VARATT_IS_COMPRESSED(DatumGetPointer(toast_values[i])))
756  continue;
757  if (att->attstorage != 'x' && att->attstorage != 'e')
758  continue;
759  if (toast_sizes[i] > biggest_size)
760  {
761  biggest_attno = i;
762  biggest_size = toast_sizes[i];
763  }
764  }
765 
766  if (biggest_attno < 0)
767  break;
768 
769  /*
770  * Attempt to compress it inline, if it has attstorage 'x'
771  */
772  i = biggest_attno;
773  if (TupleDescAttr(tupleDesc, i)->attstorage == 'x')
774  {
775  old_value = toast_values[i];
776  new_value = toast_compress_datum(old_value);
777 
778  if (DatumGetPointer(new_value) != NULL)
779  {
780  /* successful compression */
781  if (toast_free[i])
782  pfree(DatumGetPointer(old_value));
783  toast_values[i] = new_value;
784  toast_free[i] = true;
785  toast_sizes[i] = VARSIZE(DatumGetPointer(toast_values[i]));
786  need_change = true;
787  need_free = true;
788  }
789  else
790  {
791  /* incompressible, ignore on subsequent compression passes */
792  toast_action[i] = 'x';
793  }
794  }
795  else
796  {
797  /* has attstorage 'e', ignore on subsequent compression passes */
798  toast_action[i] = 'x';
799  }
800 
801  /*
802  * If this value is by itself more than maxDataLen (after compression
803  * if any), push it out to the toast table immediately, if possible.
804  * This avoids uselessly compressing other fields in the common case
805  * where we have one long field and several short ones.
806  *
807  * XXX maybe the threshold should be less than maxDataLen?
808  */
809  if (toast_sizes[i] > maxDataLen &&
810  rel->rd_rel->reltoastrelid != InvalidOid)
811  {
812  old_value = toast_values[i];
813  toast_action[i] = 'p';
814  toast_values[i] = toast_save_datum(rel, toast_values[i],
815  toast_oldexternal[i], options);
816  if (toast_free[i])
817  pfree(DatumGetPointer(old_value));
818  toast_free[i] = true;
819  need_change = true;
820  need_free = true;
821  }
822  }
823 
824  /*
825  * Second we look for attributes of attstorage 'x' or 'e' that are still
826  * inline. But skip this if there's no toast table to push them to.
827  */
828  while (heap_compute_data_size(tupleDesc,
829  toast_values, toast_isnull) > maxDataLen &&
830  rel->rd_rel->reltoastrelid != InvalidOid)
831  {
832  int biggest_attno = -1;
833  int32 biggest_size = MAXALIGN(TOAST_POINTER_SIZE);
834  Datum old_value;
835 
836  /*------
837  * Search for the biggest yet inlined attribute with
838  * attstorage equals 'x' or 'e'
839  *------
840  */
841  for (i = 0; i < numAttrs; i++)
842  {
843  Form_pg_attribute att = TupleDescAttr(tupleDesc, i);
844 
845  if (toast_action[i] == 'p')
846  continue;
847  if (VARATT_IS_EXTERNAL(DatumGetPointer(toast_values[i])))
848  continue; /* can't happen, toast_action would be 'p' */
849  if (att->attstorage != 'x' && att->attstorage != 'e')
850  continue;
851  if (toast_sizes[i] > biggest_size)
852  {
853  biggest_attno = i;
854  biggest_size = toast_sizes[i];
855  }
856  }
857 
858  if (biggest_attno < 0)
859  break;
860 
861  /*
862  * Store this external
863  */
864  i = biggest_attno;
865  old_value = toast_values[i];
866  toast_action[i] = 'p';
867  toast_values[i] = toast_save_datum(rel, toast_values[i],
868  toast_oldexternal[i], options);
869  if (toast_free[i])
870  pfree(DatumGetPointer(old_value));
871  toast_free[i] = true;
872 
873  need_change = true;
874  need_free = true;
875  }
876 
877  /*
878  * Round 3 - this time we take attributes with storage 'm' into
879  * compression
880  */
881  while (heap_compute_data_size(tupleDesc,
882  toast_values, toast_isnull) > maxDataLen)
883  {
884  int biggest_attno = -1;
885  int32 biggest_size = MAXALIGN(TOAST_POINTER_SIZE);
886  Datum old_value;
887  Datum new_value;
888 
889  /*
890  * Search for the biggest yet uncompressed internal attribute
891  */
892  for (i = 0; i < numAttrs; i++)
893  {
894  if (toast_action[i] != ' ')
895  continue;
896  if (VARATT_IS_EXTERNAL(DatumGetPointer(toast_values[i])))
897  continue; /* can't happen, toast_action would be 'p' */
898  if (VARATT_IS_COMPRESSED(DatumGetPointer(toast_values[i])))
899  continue;
900  if (TupleDescAttr(tupleDesc, i)->attstorage != 'm')
901  continue;
902  if (toast_sizes[i] > biggest_size)
903  {
904  biggest_attno = i;
905  biggest_size = toast_sizes[i];
906  }
907  }
908 
909  if (biggest_attno < 0)
910  break;
911 
912  /*
913  * Attempt to compress it inline
914  */
915  i = biggest_attno;
916  old_value = toast_values[i];
917  new_value = toast_compress_datum(old_value);
918 
919  if (DatumGetPointer(new_value) != NULL)
920  {
921  /* successful compression */
922  if (toast_free[i])
923  pfree(DatumGetPointer(old_value));
924  toast_values[i] = new_value;
925  toast_free[i] = true;
926  toast_sizes[i] = VARSIZE(DatumGetPointer(toast_values[i]));
927  need_change = true;
928  need_free = true;
929  }
930  else
931  {
932  /* incompressible, ignore on subsequent compression passes */
933  toast_action[i] = 'x';
934  }
935  }
936 
937  /*
938  * Finally we store attributes of type 'm' externally. At this point we
939  * increase the target tuple size, so that 'm' attributes aren't stored
940  * externally unless really necessary.
941  */
942  maxDataLen = TOAST_TUPLE_TARGET_MAIN - hoff;
943 
944  while (heap_compute_data_size(tupleDesc,
945  toast_values, toast_isnull) > maxDataLen &&
946  rel->rd_rel->reltoastrelid != InvalidOid)
947  {
948  int biggest_attno = -1;
949  int32 biggest_size = MAXALIGN(TOAST_POINTER_SIZE);
950  Datum old_value;
951 
952  /*--------
953  * Search for the biggest yet inlined attribute with
954  * attstorage = 'm'
955  *--------
956  */
957  for (i = 0; i < numAttrs; i++)
958  {
959  if (toast_action[i] == 'p')
960  continue;
961  if (VARATT_IS_EXTERNAL(DatumGetPointer(toast_values[i])))
962  continue; /* can't happen, toast_action would be 'p' */
963  if (TupleDescAttr(tupleDesc, i)->attstorage != 'm')
964  continue;
965  if (toast_sizes[i] > biggest_size)
966  {
967  biggest_attno = i;
968  biggest_size = toast_sizes[i];
969  }
970  }
971 
972  if (biggest_attno < 0)
973  break;
974 
975  /*
976  * Store this external
977  */
978  i = biggest_attno;
979  old_value = toast_values[i];
980  toast_action[i] = 'p';
981  toast_values[i] = toast_save_datum(rel, toast_values[i],
982  toast_oldexternal[i], options);
983  if (toast_free[i])
984  pfree(DatumGetPointer(old_value));
985  toast_free[i] = true;
986 
987  need_change = true;
988  need_free = true;
989  }
990 
991  /*
992  * In the case we toasted any values, we need to build a new heap tuple
993  * with the changed values.
994  */
995  if (need_change)
996  {
997  HeapTupleHeader olddata = newtup->t_data;
998  HeapTupleHeader new_data;
999  int32 new_header_len;
1000  int32 new_data_len;
1001  int32 new_tuple_len;
1002 
1003  /*
1004  * Calculate the new size of the tuple.
1005  *
1006  * Note: we used to assume here that the old tuple's t_hoff must equal
1007  * the new_header_len value, but that was incorrect. The old tuple
1008  * might have a smaller-than-current natts, if there's been an ALTER
1009  * TABLE ADD COLUMN since it was stored; and that would lead to a
1010  * different conclusion about the size of the null bitmap, or even
1011  * whether there needs to be one at all.
1012  */
1013  new_header_len = SizeofHeapTupleHeader;
1014  if (has_nulls)
1015  new_header_len += BITMAPLEN(numAttrs);
1016  if (olddata->t_infomask & HEAP_HASOID)
1017  new_header_len += sizeof(Oid);
1018  new_header_len = MAXALIGN(new_header_len);
1019  new_data_len = heap_compute_data_size(tupleDesc,
1020  toast_values, toast_isnull);
1021  new_tuple_len = new_header_len + new_data_len;
1022 
1023  /*
1024  * Allocate and zero the space needed, and fill HeapTupleData fields.
1025  */
1026  result_tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + new_tuple_len);
1027  result_tuple->t_len = new_tuple_len;
1028  result_tuple->t_self = newtup->t_self;
1029  result_tuple->t_tableOid = newtup->t_tableOid;
1030  new_data = (HeapTupleHeader) ((char *) result_tuple + HEAPTUPLESIZE);
1031  result_tuple->t_data = new_data;
1032 
1033  /*
1034  * Copy the existing tuple header, but adjust natts and t_hoff.
1035  */
1036  memcpy(new_data, olddata, SizeofHeapTupleHeader);
1037  HeapTupleHeaderSetNatts(new_data, numAttrs);
1038  new_data->t_hoff = new_header_len;
1039  if (olddata->t_infomask & HEAP_HASOID)
1040  HeapTupleHeaderSetOid(new_data, HeapTupleHeaderGetOid(olddata));
1041 
1042  /* Copy over the data, and fill the null bitmap if needed */
1043  heap_fill_tuple(tupleDesc,
1044  toast_values,
1045  toast_isnull,
1046  (char *) new_data + new_header_len,
1047  new_data_len,
1048  &(new_data->t_infomask),
1049  has_nulls ? new_data->t_bits : NULL);
1050  }
1051  else
1052  result_tuple = newtup;
1053 
1054  /*
1055  * Free allocated temp values
1056  */
1057  if (need_free)
1058  for (i = 0; i < numAttrs; i++)
1059  if (toast_free[i])
1060  pfree(DatumGetPointer(toast_values[i]));
1061 
1062  /*
1063  * Delete external values from the old tuple
1064  */
1065  if (need_delold)
1066  for (i = 0; i < numAttrs; i++)
1067  if (toast_delold[i])
1068  toast_delete_datum(rel, toast_oldvalues[i], false);
1069 
1070  return result_tuple;
1071 }
#define VARATT_IS_EXTERNAL_ONDISK(PTR)
Definition: postgres.h:315
#define VARATT_IS_COMPRESSED(PTR)
Definition: postgres.h:313
void heap_fill_tuple(TupleDesc tupleDesc, Datum *values, bool *isnull, char *data, Size data_size, uint16 *infomask, bits8 *bit)
Definition: heaptuple.c:145
#define SizeofHeapTupleHeader
Definition: htup_details.h:175
HeapTupleData * HeapTuple
Definition: htup.h:70
bits8 t_bits[FLEXIBLE_ARRAY_MEMBER]
Definition: htup_details.h:168
#define VARSIZE(PTR)
Definition: postgres.h:304
#define PointerGetDatum(X)
Definition: postgres.h:562
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
struct varlena * heap_tuple_fetch_attr(struct varlena *attr)
Definition: tuptoaster.c:101
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
#define TOAST_TUPLE_TARGET_MAIN
Definition: tuptoaster.h:68
#define RELKIND_MATVIEW
Definition: pg_class.h:165
#define BITMAPLEN(NATTS)
Definition: htup_details.h:553
static Datum toast_save_datum(Relation rel, Datum value, struct varlena *oldexternal, int options)
Definition: tuptoaster.c:1468
struct varlena * heap_tuple_untoast_attr(struct varlena *attr)
Definition: tuptoaster.c:172
Form_pg_class rd_rel
Definition: rel.h:114
unsigned int Oid
Definition: postgres_ext.h:31
int natts
Definition: tupdesc.h:79
#define HEAP_INSERT_SPECULATIVE
Definition: heapam.h:31
signed int int32
Definition: c.h:284
HeapTupleHeader t_data
Definition: htup.h:67
#define VARATT_IS_EXTERNAL(PTR)
Definition: postgres.h:314
void pfree(void *pointer)
Definition: mcxt.c:949
#define HeapTupleHeaderSetOid(tup, oid)
Definition: htup_details.h:478
Datum toast_compress_datum(Datum value)
Definition: tuptoaster.c:1371
ItemPointerData t_self
Definition: htup.h:65
uint32 t_len
Definition: htup.h:64
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
Oid t_tableOid
Definition: htup.h:66
void * palloc0(Size size)
Definition: mcxt.c:877
#define TOAST_POINTER_SIZE
Definition: tuptoaster.h:99
uintptr_t Datum
Definition: postgres.h:372
TupleDesc rd_att
Definition: rel.h:115
#define VARSIZE_ANY(PTR)
Definition: postgres.h:334
#define InvalidOid
Definition: postgres_ext.h:36
#define MaxHeapAttributeNumber
Definition: htup_details.h:47
#define Assert(condition)
Definition: c.h:670
#define HeapTupleHeaderSetNatts(tup, natts)
Definition: htup_details.h:540
#define TOAST_TUPLE_TARGET
Definition: tuptoaster.h:57
size_t Size
Definition: c.h:404
#define RelationGetToastTupleTarget(relation, defaulttarg)
Definition: rel.h:293
#define MAXALIGN(LEN)
Definition: c.h:623
Size heap_compute_data_size(TupleDesc tupleDesc, Datum *values, bool *isnull)
Definition: heaptuple.c:85
#define DatumGetPointer(X)
Definition: postgres.h:555
void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)
Definition: heaptuple.c:936
#define HeapTupleHeaderGetOid(tup)
Definition: htup_details.h:470
static void toast_delete_datum(Relation rel, Datum value, bool is_speculative)
Definition: tuptoaster.c:1728
#define HEAPTUPLESIZE
Definition: htup.h:72
int i
#define HEAP_HASOID
Definition: htup_details.h:183
Definition: c.h:487
#define RELKIND_RELATION
Definition: pg_class.h:160
#define VARSIZE_EXTERNAL(PTR)
Definition: postgres.h:310

◆ toast_raw_datum_size()

Size toast_raw_datum_size ( Datum  value)

Definition at line 353 of file tuptoaster.c.

References Assert, DatumGetEOHP(), DatumGetPointer, EOH_get_flat_size(), varatt_indirect::pointer, PointerGetDatum, toast_raw_datum_size(), varatt_external::va_rawsize, VARATT_EXTERNAL_GET_POINTER, VARATT_IS_COMPRESSED, VARATT_IS_EXTERNAL_EXPANDED, VARATT_IS_EXTERNAL_INDIRECT, VARATT_IS_EXTERNAL_ONDISK, VARATT_IS_SHORT, VARHDRSZ, VARHDRSZ_SHORT, VARRAWSIZE_4B_C, VARSIZE, and VARSIZE_SHORT.

Referenced by bpcharoctetlen(), byteaeq(), byteane(), byteaoctetlen(), compute_array_stats(), compute_distinct_stats(), compute_scalar_stats(), record_image_cmp(), record_image_eq(), text_length(), texteq(), textne(), textoctetlen(), and toast_raw_datum_size().

354 {
355  struct varlena *attr = (struct varlena *) DatumGetPointer(value);
356  Size result;
357 
358  if (VARATT_IS_EXTERNAL_ONDISK(attr))
359  {
360  /* va_rawsize is the size of the original datum -- including header */
361  struct varatt_external toast_pointer;
362 
363  VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
364  result = toast_pointer.va_rawsize;
365  }
366  else if (VARATT_IS_EXTERNAL_INDIRECT(attr))
367  {
368  struct varatt_indirect toast_pointer;
369 
370  VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
371 
372  /* nested indirect Datums aren't allowed */
373  Assert(!VARATT_IS_EXTERNAL_INDIRECT(toast_pointer.pointer));
374 
375  return toast_raw_datum_size(PointerGetDatum(toast_pointer.pointer));
376  }
377  else if (VARATT_IS_EXTERNAL_EXPANDED(attr))
378  {
380  }
381  else if (VARATT_IS_COMPRESSED(attr))
382  {
383  /* here, va_rawsize is just the payload size */
384  result = VARRAWSIZE_4B_C(attr) + VARHDRSZ;
385  }
386  else if (VARATT_IS_SHORT(attr))
387  {
388  /*
389  * we have to normalize the header length to VARHDRSZ or else the
390  * callers of this function will be confused.
391  */
392  result = VARSIZE_SHORT(attr) - VARHDRSZ_SHORT + VARHDRSZ;
393  }
394  else
395  {
396  /* plain untoasted datum */
397  result = VARSIZE(attr);
398  }
399  return result;
400 }
#define VARATT_IS_EXTERNAL_ONDISK(PTR)
Definition: postgres.h:315
#define VARATT_IS_COMPRESSED(PTR)
Definition: postgres.h:313
#define VARATT_IS_EXTERNAL_EXPANDED(PTR)
Definition: postgres.h:323
#define VARHDRSZ_SHORT
Definition: postgres.h:269
#define VARSIZE(PTR)
Definition: postgres.h:304
#define PointerGetDatum(X)
Definition: postgres.h:562
#define VARHDRSZ
Definition: c.h:493
Size toast_raw_datum_size(Datum value)
Definition: tuptoaster.c:353
#define VARATT_IS_EXTERNAL_INDIRECT(PTR)
Definition: postgres.h:317
#define VARATT_IS_SHORT(PTR)
Definition: postgres.h:325
static struct @121 value
Size EOH_get_flat_size(ExpandedObjectHeader *eohptr)
Definition: expandeddatum.c:75
#define VARSIZE_SHORT(PTR)
Definition: postgres.h:306
ExpandedObjectHeader * DatumGetEOHP(Datum d)
Definition: expandeddatum.c:29
#define VARRAWSIZE_4B_C(PTR)
Definition: postgres.h:284
#define Assert(condition)
Definition: c.h:670
#define VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr)
Definition: tuptoaster.h:121
size_t Size
Definition: c.h:404
#define DatumGetPointer(X)
Definition: postgres.h:555
Definition: c.h:487