PostgreSQL Source Code  git master
detoast.c File Reference
#include "postgres.h"
#include "access/detoast.h"
#include "access/genam.h"
#include "access/heaptoast.h"
#include "access/table.h"
#include "access/toast_internals.h"
#include "common/pg_lzcompress.h"
#include "utils/expandeddatum.h"
#include "utils/fmgroids.h"
#include "utils/rel.h"
Include dependency graph for detoast.c:

Go to the source code of this file.

Functions

static struct varlenatoast_fetch_datum (struct varlena *attr)
 
static struct varlenatoast_fetch_datum_slice (struct varlena *attr, int32 sliceoffset, int32 length)
 
static struct varlenatoast_decompress_datum (struct varlena *attr)
 
static struct varlenatoast_decompress_datum_slice (struct varlena *attr, int32 slicelength)
 
struct varlenadetoast_external_attr (struct varlena *attr)
 
struct varlenadetoast_attr (struct varlena *attr)
 
struct varlenadetoast_attr_slice (struct varlena *attr, int32 sliceoffset, int32 slicelength)
 
Size toast_raw_datum_size (Datum value)
 
Size toast_datum_size (Datum value)
 

Function Documentation

◆ detoast_attr()

struct varlena* detoast_attr ( struct varlena attr)

Definition at line 116 of file detoast.c.

References Assert, detoast_attr(), detoast_external_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 detoast_attr(), getdatafield(), pg_detoast_datum(), pg_detoast_datum_copy(), pg_detoast_datum_packed(), toast_flatten_tuple_to_datum(), and toast_tuple_init().

117 {
118  if (VARATT_IS_EXTERNAL_ONDISK(attr))
119  {
120  /*
121  * This is an externally stored datum --- fetch it back from there
122  */
123  attr = toast_fetch_datum(attr);
124  /* If it's compressed, decompress it */
125  if (VARATT_IS_COMPRESSED(attr))
126  {
127  struct varlena *tmp = attr;
128 
129  attr = toast_decompress_datum(tmp);
130  pfree(tmp);
131  }
132  }
133  else if (VARATT_IS_EXTERNAL_INDIRECT(attr))
134  {
135  /*
136  * This is an indirect pointer --- dereference it
137  */
138  struct varatt_indirect redirect;
139 
140  VARATT_EXTERNAL_GET_POINTER(redirect, attr);
141  attr = (struct varlena *) redirect.pointer;
142 
143  /* nested indirect Datums aren't allowed */
145 
146  /* recurse in case value is still extended in some other way */
147  attr = detoast_attr(attr);
148 
149  /* if it isn't, we'd better copy it */
150  if (attr == (struct varlena *) redirect.pointer)
151  {
152  struct varlena *result;
153 
154  result = (struct varlena *) palloc(VARSIZE_ANY(attr));
155  memcpy(result, attr, VARSIZE_ANY(attr));
156  attr = result;
157  }
158  }
159  else if (VARATT_IS_EXTERNAL_EXPANDED(attr))
160  {
161  /*
162  * This is an expanded-object pointer --- get flat format
163  */
164  attr = detoast_external_attr(attr);
165  /* flatteners are not allowed to produce compressed/short output */
166  Assert(!VARATT_IS_EXTENDED(attr));
167  }
168  else if (VARATT_IS_COMPRESSED(attr))
169  {
170  /*
171  * This is a compressed value inside of the main tuple
172  */
173  attr = toast_decompress_datum(attr);
174  }
175  else if (VARATT_IS_SHORT(attr))
176  {
177  /*
178  * This is a short-header varlena --- convert to 4-byte header format
179  */
180  Size data_size = VARSIZE_SHORT(attr) - VARHDRSZ_SHORT;
181  Size new_size = data_size + VARHDRSZ;
182  struct varlena *new_attr;
183 
184  new_attr = (struct varlena *) palloc(new_size);
185  SET_VARSIZE(new_attr, new_size);
186  memcpy(VARDATA(new_attr), VARDATA_SHORT(attr), data_size);
187  attr = new_attr;
188  }
189 
190  return attr;
191 }
#define VARATT_IS_EXTERNAL_ONDISK(PTR)
Definition: postgres.h:314
#define VARATT_IS_COMPRESSED(PTR)
Definition: postgres.h:312
#define VARDATA(PTR)
Definition: postgres.h:302
#define VARATT_IS_EXTERNAL_EXPANDED(PTR)
Definition: postgres.h:322
#define VARHDRSZ_SHORT
Definition: postgres.h:268
#define VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr)
Definition: detoast.h:32
#define VARHDRSZ
Definition: c.h:562
struct varlena * detoast_external_attr(struct varlena *attr)
Definition: detoast.c:45
struct varlena * detoast_attr(struct varlena *attr)
Definition: detoast.c:116
void pfree(void *pointer)
Definition: mcxt.c:1056
#define VARATT_IS_EXTERNAL_INDIRECT(PTR)
Definition: postgres.h:316
#define VARATT_IS_SHORT(PTR)
Definition: postgres.h:326
#define VARSIZE_SHORT(PTR)
Definition: postgres.h:305
#define VARSIZE_ANY(PTR)
Definition: postgres.h:335
static struct varlena * toast_fetch_datum(struct varlena *attr)
Definition: detoast.c:324
#define Assert(condition)
Definition: c.h:739
size_t Size
Definition: c.h:467
#define VARATT_IS_EXTENDED(PTR)
Definition: postgres.h:327
#define VARDATA_SHORT(PTR)
Definition: postgres.h:306
void * palloc(Size size)
Definition: mcxt.c:949
Definition: c.h:556
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329
static struct varlena * toast_decompress_datum(struct varlena *attr)
Definition: detoast.c:750

◆ detoast_attr_slice()

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

Definition at line 204 of file detoast.c.

References Assert, detoast_attr_slice(), detoast_external_attr(), palloc(), pfree(), pglz_maximum_compressed_size(), varatt_indirect::pointer, SET_VARSIZE, toast_decompress_datum(), toast_decompress_datum_slice(), toast_fetch_datum(), toast_fetch_datum_slice(), varatt_external::va_extsize, 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 detoast_attr_slice(), and pg_detoast_datum_slice().

206 {
207  struct varlena *preslice;
208  struct varlena *result;
209  char *attrdata;
210  int32 attrsize;
211 
212  if (VARATT_IS_EXTERNAL_ONDISK(attr))
213  {
214  struct varatt_external toast_pointer;
215 
216  VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
217 
218  /* fast path for non-compressed external datums */
219  if (!VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer))
220  return toast_fetch_datum_slice(attr, sliceoffset, slicelength);
221 
222  /*
223  * For compressed values, we need to fetch enough slices to decompress
224  * at least the requested part (when a prefix is requested). Otherwise,
225  * just fetch all slices.
226  */
227  if (slicelength > 0 && sliceoffset >= 0)
228  {
229  int32 max_size;
230 
231  /*
232  * Determine maximum amount of compressed data needed for a prefix
233  * of a given length (after decompression).
234  */
235  max_size = pglz_maximum_compressed_size(sliceoffset + slicelength,
236  toast_pointer.va_extsize);
237 
238  /*
239  * Fetch enough compressed slices (compressed marker will get set
240  * automatically).
241  */
242  preslice = toast_fetch_datum_slice(attr, 0, max_size);
243  }
244  else
245  preslice = toast_fetch_datum(attr);
246  }
247  else if (VARATT_IS_EXTERNAL_INDIRECT(attr))
248  {
249  struct varatt_indirect redirect;
250 
251  VARATT_EXTERNAL_GET_POINTER(redirect, attr);
252 
253  /* nested indirect Datums aren't allowed */
254  Assert(!VARATT_IS_EXTERNAL_INDIRECT(redirect.pointer));
255 
256  return detoast_attr_slice(redirect.pointer,
257  sliceoffset, slicelength);
258  }
259  else if (VARATT_IS_EXTERNAL_EXPANDED(attr))
260  {
261  /* pass it off to detoast_external_attr to flatten */
262  preslice = detoast_external_attr(attr);
263  }
264  else
265  preslice = attr;
266 
267  Assert(!VARATT_IS_EXTERNAL(preslice));
268 
269  if (VARATT_IS_COMPRESSED(preslice))
270  {
271  struct varlena *tmp = preslice;
272 
273  /* Decompress enough to encompass the slice and the offset */
274  if (slicelength > 0 && sliceoffset >= 0)
275  preslice = toast_decompress_datum_slice(tmp, slicelength + sliceoffset);
276  else
277  preslice = toast_decompress_datum(tmp);
278 
279  if (tmp != attr)
280  pfree(tmp);
281  }
282 
283  if (VARATT_IS_SHORT(preslice))
284  {
285  attrdata = VARDATA_SHORT(preslice);
286  attrsize = VARSIZE_SHORT(preslice) - VARHDRSZ_SHORT;
287  }
288  else
289  {
290  attrdata = VARDATA(preslice);
291  attrsize = VARSIZE(preslice) - VARHDRSZ;
292  }
293 
294  /* slicing of datum for compressed cases and plain value */
295 
296  if (sliceoffset >= attrsize)
297  {
298  sliceoffset = 0;
299  slicelength = 0;
300  }
301 
302  if (((sliceoffset + slicelength) > attrsize) || slicelength < 0)
303  slicelength = attrsize - sliceoffset;
304 
305  result = (struct varlena *) palloc(slicelength + VARHDRSZ);
306  SET_VARSIZE(result, slicelength + VARHDRSZ);
307 
308  memcpy(VARDATA(result), attrdata + sliceoffset, slicelength);
309 
310  if (preslice != attr)
311  pfree(preslice);
312 
313  return result;
314 }
#define VARATT_IS_EXTERNAL_ONDISK(PTR)
Definition: postgres.h:314
#define VARATT_IS_COMPRESSED(PTR)
Definition: postgres.h:312
int32 pglz_maximum_compressed_size(int32 rawsize, int32 total_compressed_size)
#define VARDATA(PTR)
Definition: postgres.h:302
#define VARATT_IS_EXTERNAL_EXPANDED(PTR)
Definition: postgres.h:322
static struct varlena * toast_fetch_datum_slice(struct varlena *attr, int32 sliceoffset, int32 length)
Definition: detoast.c:509
#define VARHDRSZ_SHORT
Definition: postgres.h:268
#define VARSIZE(PTR)
Definition: postgres.h:303
#define VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr)
Definition: detoast.h:32
#define VARHDRSZ
Definition: c.h:562
struct varlena * detoast_external_attr(struct varlena *attr)
Definition: detoast.c:45
struct varlena * detoast_attr_slice(struct varlena *attr, int32 sliceoffset, int32 slicelength)
Definition: detoast.c:204
signed int int32
Definition: c.h:347
#define VARATT_IS_EXTERNAL(PTR)
Definition: postgres.h:313
void pfree(void *pointer)
Definition: mcxt.c:1056
#define VARATT_IS_EXTERNAL_INDIRECT(PTR)
Definition: postgres.h:316
#define VARATT_IS_SHORT(PTR)
Definition: postgres.h:326
#define VARSIZE_SHORT(PTR)
Definition: postgres.h:305
static struct varlena * toast_fetch_datum(struct varlena *attr)
Definition: detoast.c:324
#define Assert(condition)
Definition: c.h:739
#define VARDATA_SHORT(PTR)
Definition: postgres.h:306
void * palloc(Size size)
Definition: mcxt.c:949
#define VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer)
Definition: detoast.h:22
Definition: c.h:556
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329
static struct varlena * toast_decompress_datum(struct varlena *attr)
Definition: detoast.c:750
static struct varlena * toast_decompress_datum_slice(struct varlena *attr, int32 slicelength)
Definition: detoast.c:778

◆ detoast_external_attr()

struct varlena* detoast_external_attr ( struct varlena attr)

Definition at line 45 of file detoast.c.

References Assert, DatumGetEOHP(), detoast_external_attr(), EOH_flatten_into(), EOH_get_flat_size(), 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 assign_simple_var(), detoast_attr(), detoast_attr_slice(), detoast_external_attr(), expanded_record_set_field_internal(), expanded_record_set_fields(), index_form_tuple(), make_tuple_indirect(), toast_build_flattened_tuple(), toast_flatten_tuple(), toast_tuple_init(), and tstoreReceiveSlot_detoast().

46 {
47  struct varlena *result;
48 
49  if (VARATT_IS_EXTERNAL_ONDISK(attr))
50  {
51  /*
52  * This is an external stored plain value
53  */
54  result = toast_fetch_datum(attr);
55  }
56  else if (VARATT_IS_EXTERNAL_INDIRECT(attr))
57  {
58  /*
59  * This is an indirect pointer --- dereference it
60  */
61  struct varatt_indirect redirect;
62 
63  VARATT_EXTERNAL_GET_POINTER(redirect, attr);
64  attr = (struct varlena *) redirect.pointer;
65 
66  /* nested indirect Datums aren't allowed */
68 
69  /* recurse if value is still external in some other way */
70  if (VARATT_IS_EXTERNAL(attr))
71  return detoast_external_attr(attr);
72 
73  /*
74  * Copy into the caller's memory context, in case caller tries to
75  * pfree the result.
76  */
77  result = (struct varlena *) palloc(VARSIZE_ANY(attr));
78  memcpy(result, attr, VARSIZE_ANY(attr));
79  }
80  else if (VARATT_IS_EXTERNAL_EXPANDED(attr))
81  {
82  /*
83  * This is an expanded-object pointer --- get flat format
84  */
86  Size resultsize;
87 
88  eoh = DatumGetEOHP(PointerGetDatum(attr));
89  resultsize = EOH_get_flat_size(eoh);
90  result = (struct varlena *) palloc(resultsize);
91  EOH_flatten_into(eoh, (void *) result, resultsize);
92  }
93  else
94  {
95  /*
96  * This is a plain value inside of the main tuple - why am I called?
97  */
98  result = attr;
99  }
100 
101  return result;
102 }
#define VARATT_IS_EXTERNAL_ONDISK(PTR)
Definition: postgres.h:314
#define VARATT_IS_EXTERNAL_EXPANDED(PTR)
Definition: postgres.h:322
#define VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr)
Definition: detoast.h:32
#define PointerGetDatum(X)
Definition: postgres.h:556
struct varlena * detoast_external_attr(struct varlena *attr)
Definition: detoast.c:45
#define VARATT_IS_EXTERNAL(PTR)
Definition: postgres.h:313
#define VARATT_IS_EXTERNAL_INDIRECT(PTR)
Definition: postgres.h:316
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:335
static struct varlena * toast_fetch_datum(struct varlena *attr)
Definition: detoast.c:324
#define Assert(condition)
Definition: c.h:739
size_t Size
Definition: c.h:467
void * palloc(Size size)
Definition: mcxt.c:949
Definition: c.h:556

◆ toast_datum_size()

Size toast_datum_size ( Datum  value)

Definition at line 862 of file detoast.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().

863 {
864  struct varlena *attr = (struct varlena *) DatumGetPointer(value);
865  Size result;
866 
867  if (VARATT_IS_EXTERNAL_ONDISK(attr))
868  {
869  /*
870  * Attribute is stored externally - return the extsize whether
871  * compressed or not. We do not count the size of the toast pointer
872  * ... should we?
873  */
874  struct varatt_external toast_pointer;
875 
876  VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
877  result = toast_pointer.va_extsize;
878  }
879  else if (VARATT_IS_EXTERNAL_INDIRECT(attr))
880  {
881  struct varatt_indirect toast_pointer;
882 
883  VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
884 
885  /* nested indirect Datums aren't allowed */
887 
888  return toast_datum_size(PointerGetDatum(toast_pointer.pointer));
889  }
890  else if (VARATT_IS_EXTERNAL_EXPANDED(attr))
891  {
893  }
894  else if (VARATT_IS_SHORT(attr))
895  {
896  result = VARSIZE_SHORT(attr);
897  }
898  else
899  {
900  /*
901  * Attribute is stored inline either compressed or not, just calculate
902  * the size of the datum in either case.
903  */
904  result = VARSIZE(attr);
905  }
906  return result;
907 }
#define VARATT_IS_EXTERNAL_ONDISK(PTR)
Definition: postgres.h:314
#define VARATT_IS_EXTERNAL_EXPANDED(PTR)
Definition: postgres.h:322
#define VARSIZE(PTR)
Definition: postgres.h:303
#define VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr)
Definition: detoast.h:32
#define PointerGetDatum(X)
Definition: postgres.h:556
static struct @145 value
Size toast_datum_size(Datum value)
Definition: detoast.c:862
#define VARATT_IS_EXTERNAL_INDIRECT(PTR)
Definition: postgres.h:316
#define VARATT_IS_SHORT(PTR)
Definition: postgres.h:326
Size EOH_get_flat_size(ExpandedObjectHeader *eohptr)
Definition: expandeddatum.c:75
#define VARSIZE_SHORT(PTR)
Definition: postgres.h:305
ExpandedObjectHeader * DatumGetEOHP(Datum d)
Definition: expandeddatum.c:29
#define Assert(condition)
Definition: c.h:739
size_t Size
Definition: c.h:467
#define DatumGetPointer(X)
Definition: postgres.h:549
Definition: c.h:556

◆ toast_decompress_datum()

static struct varlena * toast_decompress_datum ( struct varlena attr)
static

Definition at line 750 of file detoast.c.

References Assert, elog, ERROR, palloc(), pglz_decompress(), SET_VARSIZE, TOAST_COMPRESS_RAWDATA, TOAST_COMPRESS_RAWSIZE, TOAST_COMPRESS_SIZE, VARATT_IS_COMPRESSED, VARDATA, and VARHDRSZ.

Referenced by detoast_attr(), and detoast_attr_slice().

751 {
752  struct varlena *result;
753 
755 
756  result = (struct varlena *)
759 
761  TOAST_COMPRESS_SIZE(attr),
762  VARDATA(result),
763  TOAST_COMPRESS_RAWSIZE(attr), true) < 0)
764  elog(ERROR, "compressed data is corrupted");
765 
766  return result;
767 }
#define VARATT_IS_COMPRESSED(PTR)
Definition: postgres.h:312
#define VARDATA(PTR)
Definition: postgres.h:302
#define VARHDRSZ
Definition: c.h:562
int32 pglz_decompress(const char *source, int32 slen, char *dest, int32 rawsize, bool check_complete)
#define ERROR
Definition: elog.h:43
#define TOAST_COMPRESS_RAWDATA(ptr)
#define TOAST_COMPRESS_SIZE(ptr)
#define Assert(condition)
Definition: c.h:739
void * palloc(Size size)
Definition: mcxt.c:949
#define elog(elevel,...)
Definition: elog.h:228
Definition: c.h:556
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329
#define TOAST_COMPRESS_RAWSIZE(ptr)

◆ toast_decompress_datum_slice()

static struct varlena * toast_decompress_datum_slice ( struct varlena attr,
int32  slicelength 
)
static

Definition at line 778 of file detoast.c.

References Assert, elog, ERROR, palloc(), pglz_decompress(), SET_VARSIZE, TOAST_COMPRESS_HDRSZ, TOAST_COMPRESS_RAWDATA, VARATT_IS_COMPRESSED, VARDATA, VARHDRSZ, and VARSIZE.

Referenced by detoast_attr_slice().

779 {
780  struct varlena *result;
781  int32 rawsize;
782 
784 
785  result = (struct varlena *) palloc(slicelength + VARHDRSZ);
786 
787  rawsize = pglz_decompress(TOAST_COMPRESS_RAWDATA(attr),
789  VARDATA(result),
790  slicelength, false);
791  if (rawsize < 0)
792  elog(ERROR, "compressed data is corrupted");
793 
794  SET_VARSIZE(result, rawsize + VARHDRSZ);
795  return result;
796 }
#define VARATT_IS_COMPRESSED(PTR)
Definition: postgres.h:312
#define VARDATA(PTR)
Definition: postgres.h:302
#define VARSIZE(PTR)
Definition: postgres.h:303
#define VARHDRSZ
Definition: c.h:562
int32 pglz_decompress(const char *source, int32 slen, char *dest, int32 rawsize, bool check_complete)
signed int int32
Definition: c.h:347
#define ERROR
Definition: elog.h:43
#define TOAST_COMPRESS_RAWDATA(ptr)
#define Assert(condition)
Definition: c.h:739
#define TOAST_COMPRESS_HDRSZ
void * palloc(Size size)
Definition: mcxt.c:949
#define elog(elevel,...)
Definition: elog.h:228
Definition: c.h:556
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329

◆ toast_fetch_datum()

static struct varlena * toast_fetch_datum ( struct varlena attr)
static

Definition at line 324 of file detoast.c.

References AccessShareLock, Assert, BTEqualStrategyNumber, DatumGetInt32, DatumGetPointer, elog, ereport, errcode(), ERRCODE_DATA_CORRUPTED, errmsg_internal(), ERROR, fastgetattr, ForwardScanDirection, init_toast_snapshot(), ObjectIdGetDatum, palloc(), RelationData::rd_att, RelationGetRelationName, ScanKeyInit(), SET_VARSIZE, SET_VARSIZE_COMPRESSED, systable_beginscan_ordered(), systable_endscan_ordered(), systable_getnext_ordered(), table_close(), table_open(), toast_close_indexes(), TOAST_MAX_CHUNK_SIZE, toast_open_indexes(), varatt_external::va_extsize, varatt_external::va_toastrelid, varatt_external::va_valueid, VARATT_EXTERNAL_GET_POINTER, VARATT_EXTERNAL_IS_COMPRESSED, VARATT_IS_EXTENDED, VARATT_IS_EXTERNAL_ONDISK, VARATT_IS_SHORT, VARDATA, VARDATA_SHORT, VARHDRSZ, VARHDRSZ_SHORT, VARSIZE, and VARSIZE_SHORT.

Referenced by detoast_attr(), detoast_attr_slice(), and detoast_external_attr().

325 {
326  Relation toastrel;
327  Relation *toastidxs;
328  ScanKeyData toastkey;
329  SysScanDesc toastscan;
330  HeapTuple ttup;
331  TupleDesc toasttupDesc;
332  struct varlena *result;
333  struct varatt_external toast_pointer;
334  int32 ressize;
335  int32 residx,
336  nextidx;
337  int32 numchunks;
338  Pointer chunk;
339  bool isnull;
340  char *chunkdata;
341  int32 chunksize;
342  int num_indexes;
343  int validIndex;
344  SnapshotData SnapshotToast;
345 
346  if (!VARATT_IS_EXTERNAL_ONDISK(attr))
347  elog(ERROR, "toast_fetch_datum shouldn't be called for non-ondisk datums");
348 
349  /* Must copy to access aligned fields */
350  VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
351 
352  ressize = toast_pointer.va_extsize;
353  numchunks = ((ressize - 1) / TOAST_MAX_CHUNK_SIZE) + 1;
354 
355  result = (struct varlena *) palloc(ressize + VARHDRSZ);
356 
357  if (VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer))
358  SET_VARSIZE_COMPRESSED(result, ressize + VARHDRSZ);
359  else
360  SET_VARSIZE(result, ressize + VARHDRSZ);
361 
362  /*
363  * Open the toast relation and its indexes
364  */
365  toastrel = table_open(toast_pointer.va_toastrelid, AccessShareLock);
366  toasttupDesc = toastrel->rd_att;
367 
368  /* Look for the valid index of the toast relation */
369  validIndex = toast_open_indexes(toastrel,
371  &toastidxs,
372  &num_indexes);
373 
374  /*
375  * Setup a scan key to fetch from the index by va_valueid
376  */
377  ScanKeyInit(&toastkey,
378  (AttrNumber) 1,
379  BTEqualStrategyNumber, F_OIDEQ,
380  ObjectIdGetDatum(toast_pointer.va_valueid));
381 
382  /*
383  * Read the chunks by index
384  *
385  * Note that because the index is actually on (valueid, chunkidx) we will
386  * see the chunks in chunkidx order, even though we didn't explicitly ask
387  * for it.
388  */
389  nextidx = 0;
390 
391  init_toast_snapshot(&SnapshotToast);
392  toastscan = systable_beginscan_ordered(toastrel, toastidxs[validIndex],
393  &SnapshotToast, 1, &toastkey);
394  while ((ttup = systable_getnext_ordered(toastscan, ForwardScanDirection)) != NULL)
395  {
396  /*
397  * Have a chunk, extract the sequence number and the data
398  */
399  residx = DatumGetInt32(fastgetattr(ttup, 2, toasttupDesc, &isnull));
400  Assert(!isnull);
401  chunk = DatumGetPointer(fastgetattr(ttup, 3, toasttupDesc, &isnull));
402  Assert(!isnull);
403  if (!VARATT_IS_EXTENDED(chunk))
404  {
405  chunksize = VARSIZE(chunk) - VARHDRSZ;
406  chunkdata = VARDATA(chunk);
407  }
408  else if (VARATT_IS_SHORT(chunk))
409  {
410  /* could happen due to heap_form_tuple doing its thing */
411  chunksize = VARSIZE_SHORT(chunk) - VARHDRSZ_SHORT;
412  chunkdata = VARDATA_SHORT(chunk);
413  }
414  else
415  {
416  /* should never happen */
417  elog(ERROR, "found toasted toast chunk for toast value %u in %s",
418  toast_pointer.va_valueid,
419  RelationGetRelationName(toastrel));
420  chunksize = 0; /* keep compiler quiet */
421  chunkdata = NULL;
422  }
423 
424  /*
425  * Some checks on the data we've found
426  */
427  if (residx != nextidx)
428  ereport(ERROR,
430  errmsg_internal("unexpected chunk number %d (expected %d) for toast value %u in %s",
431  residx, nextidx,
432  toast_pointer.va_valueid,
433  RelationGetRelationName(toastrel))));
434  if (residx < numchunks - 1)
435  {
436  if (chunksize != TOAST_MAX_CHUNK_SIZE)
437  ereport(ERROR,
439  errmsg_internal("unexpected chunk size %d (expected %d) in chunk %d of %d for toast value %u in %s",
440  chunksize, (int) TOAST_MAX_CHUNK_SIZE,
441  residx, numchunks,
442  toast_pointer.va_valueid,
443  RelationGetRelationName(toastrel))));
444  }
445  else if (residx == numchunks - 1)
446  {
447  if ((residx * TOAST_MAX_CHUNK_SIZE + chunksize) != ressize)
448  ereport(ERROR,
450  errmsg_internal("unexpected chunk size %d (expected %d) in final chunk %d for toast value %u in %s",
451  chunksize,
452  (int) (ressize - residx * TOAST_MAX_CHUNK_SIZE),
453  residx,
454  toast_pointer.va_valueid,
455  RelationGetRelationName(toastrel))));
456  }
457  else
458  ereport(ERROR,
460  errmsg_internal("unexpected chunk number %d (out of range %d..%d) for toast value %u in %s",
461  residx,
462  0, numchunks - 1,
463  toast_pointer.va_valueid,
464  RelationGetRelationName(toastrel))));
465 
466  /*
467  * Copy the data into proper place in our result
468  */
469  memcpy(VARDATA(result) + residx * TOAST_MAX_CHUNK_SIZE,
470  chunkdata,
471  chunksize);
472 
473  nextidx++;
474  }
475 
476  /*
477  * Final checks that we successfully fetched the datum
478  */
479  if (nextidx != numchunks)
480  ereport(ERROR,
482  errmsg_internal("missing chunk number %d for toast value %u in %s",
483  nextidx,
484  toast_pointer.va_valueid,
485  RelationGetRelationName(toastrel))));
486 
487  /*
488  * End scan and close relations
489  */
490  systable_endscan_ordered(toastscan);
491  toast_close_indexes(toastidxs, num_indexes, AccessShareLock);
492  table_close(toastrel, AccessShareLock);
493 
494  return result;
495 }
#define VARATT_IS_EXTERNAL_ONDISK(PTR)
Definition: postgres.h:314
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define VARDATA(PTR)
Definition: postgres.h:302
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:712
#define TOAST_MAX_CHUNK_SIZE
Definition: heaptoast.h:84
#define DatumGetInt32(X)
Definition: postgres.h:472
#define VARHDRSZ_SHORT
Definition: postgres.h:268
#define VARSIZE(PTR)
Definition: postgres.h:303
#define VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr)
Definition: detoast.h:32
void init_toast_snapshot(Snapshot toast_snapshot)
#define VARHDRSZ
Definition: c.h:562
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:608
HeapTuple systable_getnext_ordered(SysScanDesc sysscan, ScanDirection direction)
Definition: genam.c:630
signed int int32
Definition: c.h:347
char * Pointer
Definition: c.h:336
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define VARATT_IS_SHORT(PTR)
Definition: postgres.h:326
void toast_close_indexes(Relation *toastidxs, int num_indexes, LOCKMODE lock)
#define RelationGetRelationName(relation)
Definition: rel.h:456
#define ereport(elevel, rest)
Definition: elog.h:141
#define VARSIZE_SHORT(PTR)
Definition: postgres.h:305
#define ERRCODE_DATA_CORRUPTED
Definition: pg_basebackup.c:45
int toast_open_indexes(Relation toastrel, LOCKMODE lock, Relation **toastidxs, int *num_indexes)
void systable_endscan_ordered(SysScanDesc sysscan)
Definition: genam.c:649
TupleDesc rd_att
Definition: rel.h:84
int errmsg_internal(const char *fmt,...)
Definition: elog.c:909
#define Assert(condition)
Definition: c.h:739
#define VARATT_IS_EXTENDED(PTR)
Definition: postgres.h:327
#define DatumGetPointer(X)
Definition: postgres.h:549
#define VARDATA_SHORT(PTR)
Definition: postgres.h:306
void * palloc(Size size)
Definition: mcxt.c:949
SysScanDesc systable_beginscan_ordered(Relation heapRelation, Relation indexRelation, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:565
#define elog(elevel,...)
Definition: elog.h:228
#define SET_VARSIZE_COMPRESSED(PTR, len)
Definition: postgres.h:331
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer)
Definition: detoast.h:22
Definition: c.h:556
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
int16 AttrNumber
Definition: attnum.h:21
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ toast_fetch_datum_slice()

static struct varlena * toast_fetch_datum_slice ( struct varlena attr,
int32  sliceoffset,
int32  length 
)
static

Definition at line 509 of file detoast.c.

References AccessShareLock, Assert, BTEqualStrategyNumber, BTGreaterEqualStrategyNumber, BTLessEqualStrategyNumber, DatumGetInt32, DatumGetPointer, elog, ERROR, fastgetattr, ForwardScanDirection, init_toast_snapshot(), Int32GetDatum, ObjectIdGetDatum, palloc(), RelationData::rd_att, RelationGetRelationName, ScanKeyInit(), SET_VARSIZE, SET_VARSIZE_COMPRESSED, systable_beginscan_ordered(), systable_endscan_ordered(), systable_getnext_ordered(), table_close(), table_open(), toast_close_indexes(), TOAST_MAX_CHUNK_SIZE, toast_open_indexes(), varatt_external::va_extsize, varatt_external::va_toastrelid, varatt_external::va_valueid, VARATT_EXTERNAL_GET_POINTER, VARATT_EXTERNAL_IS_COMPRESSED, VARATT_IS_EXTENDED, VARATT_IS_EXTERNAL_ONDISK, VARATT_IS_SHORT, VARDATA, VARDATA_SHORT, VARHDRSZ, VARHDRSZ_SHORT, VARSIZE, and VARSIZE_SHORT.

Referenced by detoast_attr_slice().

510 {
511  Relation toastrel;
512  Relation *toastidxs;
513  ScanKeyData toastkey[3];
514  int nscankeys;
515  SysScanDesc toastscan;
516  HeapTuple ttup;
517  TupleDesc toasttupDesc;
518  struct varlena *result;
519  struct varatt_external toast_pointer;
520  int32 attrsize;
521  int32 residx;
522  int32 nextidx;
523  int numchunks;
524  int startchunk;
525  int endchunk;
526  int32 startoffset;
527  int32 endoffset;
528  int totalchunks;
529  Pointer chunk;
530  bool isnull;
531  char *chunkdata;
532  int32 chunksize;
533  int32 chcpystrt;
534  int32 chcpyend;
535  int num_indexes;
536  int validIndex;
537  SnapshotData SnapshotToast;
538 
539  if (!VARATT_IS_EXTERNAL_ONDISK(attr))
540  elog(ERROR, "toast_fetch_datum_slice shouldn't be called for non-ondisk datums");
541 
542  /* Must copy to access aligned fields */
543  VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
544 
545  /*
546  * It's nonsense to fetch slices of a compressed datum unless when it's
547  * a prefix -- this isn't lo_* we can't return a compressed datum which
548  * is meaningful to toast later.
549  */
550  Assert(!VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer) || 0 == sliceoffset);
551 
552  attrsize = toast_pointer.va_extsize;
553  totalchunks = ((attrsize - 1) / TOAST_MAX_CHUNK_SIZE) + 1;
554 
555  if (sliceoffset >= attrsize)
556  {
557  sliceoffset = 0;
558  length = 0;
559  }
560 
561  /*
562  * When fetching a prefix of a compressed external datum, account for the
563  * rawsize tracking amount of raw data, which is stored at the beginning
564  * as an int32 value).
565  */
566  if (VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer) && length > 0)
567  length = length + sizeof(int32);
568 
569  if (((sliceoffset + length) > attrsize) || length < 0)
570  length = attrsize - sliceoffset;
571 
572  result = (struct varlena *) palloc(length + VARHDRSZ);
573 
574  if (VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer))
575  SET_VARSIZE_COMPRESSED(result, length + VARHDRSZ);
576  else
577  SET_VARSIZE(result, length + VARHDRSZ);
578 
579  if (length == 0)
580  return result; /* Can save a lot of work at this point! */
581 
582  startchunk = sliceoffset / TOAST_MAX_CHUNK_SIZE;
583  endchunk = (sliceoffset + length - 1) / TOAST_MAX_CHUNK_SIZE;
584  numchunks = (endchunk - startchunk) + 1;
585 
586  startoffset = sliceoffset % TOAST_MAX_CHUNK_SIZE;
587  endoffset = (sliceoffset + length - 1) % TOAST_MAX_CHUNK_SIZE;
588 
589  /*
590  * Open the toast relation and its indexes
591  */
592  toastrel = table_open(toast_pointer.va_toastrelid, AccessShareLock);
593  toasttupDesc = toastrel->rd_att;
594 
595  /* Look for the valid index of toast relation */
596  validIndex = toast_open_indexes(toastrel,
598  &toastidxs,
599  &num_indexes);
600 
601  /*
602  * Setup a scan key to fetch from the index. This is either two keys or
603  * three depending on the number of chunks.
604  */
605  ScanKeyInit(&toastkey[0],
606  (AttrNumber) 1,
607  BTEqualStrategyNumber, F_OIDEQ,
608  ObjectIdGetDatum(toast_pointer.va_valueid));
609 
610  /*
611  * Use equality condition for one chunk, a range condition otherwise:
612  */
613  if (numchunks == 1)
614  {
615  ScanKeyInit(&toastkey[1],
616  (AttrNumber) 2,
617  BTEqualStrategyNumber, F_INT4EQ,
618  Int32GetDatum(startchunk));
619  nscankeys = 2;
620  }
621  else
622  {
623  ScanKeyInit(&toastkey[1],
624  (AttrNumber) 2,
626  Int32GetDatum(startchunk));
627  ScanKeyInit(&toastkey[2],
628  (AttrNumber) 2,
629  BTLessEqualStrategyNumber, F_INT4LE,
630  Int32GetDatum(endchunk));
631  nscankeys = 3;
632  }
633 
634  /*
635  * Read the chunks by index
636  *
637  * The index is on (valueid, chunkidx) so they will come in order
638  */
639  init_toast_snapshot(&SnapshotToast);
640  nextidx = startchunk;
641  toastscan = systable_beginscan_ordered(toastrel, toastidxs[validIndex],
642  &SnapshotToast, nscankeys, toastkey);
643  while ((ttup = systable_getnext_ordered(toastscan, ForwardScanDirection)) != NULL)
644  {
645  /*
646  * Have a chunk, extract the sequence number and the data
647  */
648  residx = DatumGetInt32(fastgetattr(ttup, 2, toasttupDesc, &isnull));
649  Assert(!isnull);
650  chunk = DatumGetPointer(fastgetattr(ttup, 3, toasttupDesc, &isnull));
651  Assert(!isnull);
652  if (!VARATT_IS_EXTENDED(chunk))
653  {
654  chunksize = VARSIZE(chunk) - VARHDRSZ;
655  chunkdata = VARDATA(chunk);
656  }
657  else if (VARATT_IS_SHORT(chunk))
658  {
659  /* could happen due to heap_form_tuple doing its thing */
660  chunksize = VARSIZE_SHORT(chunk) - VARHDRSZ_SHORT;
661  chunkdata = VARDATA_SHORT(chunk);
662  }
663  else
664  {
665  /* should never happen */
666  elog(ERROR, "found toasted toast chunk for toast value %u in %s",
667  toast_pointer.va_valueid,
668  RelationGetRelationName(toastrel));
669  chunksize = 0; /* keep compiler quiet */
670  chunkdata = NULL;
671  }
672 
673  /*
674  * Some checks on the data we've found
675  */
676  if ((residx != nextidx) || (residx > endchunk) || (residx < startchunk))
677  elog(ERROR, "unexpected chunk number %d (expected %d) for toast value %u in %s",
678  residx, nextidx,
679  toast_pointer.va_valueid,
680  RelationGetRelationName(toastrel));
681  if (residx < totalchunks - 1)
682  {
683  if (chunksize != TOAST_MAX_CHUNK_SIZE)
684  elog(ERROR, "unexpected chunk size %d (expected %d) in chunk %d of %d for toast value %u in %s when fetching slice",
685  chunksize, (int) TOAST_MAX_CHUNK_SIZE,
686  residx, totalchunks,
687  toast_pointer.va_valueid,
688  RelationGetRelationName(toastrel));
689  }
690  else if (residx == totalchunks - 1)
691  {
692  if ((residx * TOAST_MAX_CHUNK_SIZE + chunksize) != attrsize)
693  elog(ERROR, "unexpected chunk size %d (expected %d) in final chunk %d for toast value %u in %s when fetching slice",
694  chunksize,
695  (int) (attrsize - residx * TOAST_MAX_CHUNK_SIZE),
696  residx,
697  toast_pointer.va_valueid,
698  RelationGetRelationName(toastrel));
699  }
700  else
701  elog(ERROR, "unexpected chunk number %d (out of range %d..%d) for toast value %u in %s",
702  residx,
703  0, totalchunks - 1,
704  toast_pointer.va_valueid,
705  RelationGetRelationName(toastrel));
706 
707  /*
708  * Copy the data into proper place in our result
709  */
710  chcpystrt = 0;
711  chcpyend = chunksize - 1;
712  if (residx == startchunk)
713  chcpystrt = startoffset;
714  if (residx == endchunk)
715  chcpyend = endoffset;
716 
717  memcpy(VARDATA(result) +
718  (residx * TOAST_MAX_CHUNK_SIZE - sliceoffset) + chcpystrt,
719  chunkdata + chcpystrt,
720  (chcpyend - chcpystrt) + 1);
721 
722  nextidx++;
723  }
724 
725  /*
726  * Final checks that we successfully fetched the datum
727  */
728  if (nextidx != (endchunk + 1))
729  elog(ERROR, "missing chunk number %d for toast value %u in %s",
730  nextidx,
731  toast_pointer.va_valueid,
732  RelationGetRelationName(toastrel));
733 
734  /*
735  * End scan and close relations
736  */
737  systable_endscan_ordered(toastscan);
738  toast_close_indexes(toastidxs, num_indexes, AccessShareLock);
739  table_close(toastrel, AccessShareLock);
740 
741  return result;
742 }
#define VARATT_IS_EXTERNAL_ONDISK(PTR)
Definition: postgres.h:314
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define VARDATA(PTR)
Definition: postgres.h:302
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:712
#define TOAST_MAX_CHUNK_SIZE
Definition: heaptoast.h:84
#define DatumGetInt32(X)
Definition: postgres.h:472
#define VARHDRSZ_SHORT
Definition: postgres.h:268
#define VARSIZE(PTR)
Definition: postgres.h:303
#define VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr)
Definition: detoast.h:32
void init_toast_snapshot(Snapshot toast_snapshot)
#define VARHDRSZ
Definition: c.h:562
#define AccessShareLock
Definition: lockdefs.h:36
HeapTuple systable_getnext_ordered(SysScanDesc sysscan, ScanDirection direction)
Definition: genam.c:630
signed int int32
Definition: c.h:347
#define BTLessEqualStrategyNumber
Definition: stratnum.h:30
char * Pointer
Definition: c.h:336
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define VARATT_IS_SHORT(PTR)
Definition: postgres.h:326
void toast_close_indexes(Relation *toastidxs, int num_indexes, LOCKMODE lock)
#define RelationGetRelationName(relation)
Definition: rel.h:456
#define VARSIZE_SHORT(PTR)
Definition: postgres.h:305
int toast_open_indexes(Relation toastrel, LOCKMODE lock, Relation **toastidxs, int *num_indexes)
void systable_endscan_ordered(SysScanDesc sysscan)
Definition: genam.c:649
TupleDesc rd_att
Definition: rel.h:84
#define Assert(condition)
Definition: c.h:739
#define VARATT_IS_EXTENDED(PTR)
Definition: postgres.h:327
#define DatumGetPointer(X)
Definition: postgres.h:549
#define VARDATA_SHORT(PTR)
Definition: postgres.h:306
#define Int32GetDatum(X)
Definition: postgres.h:479
void * palloc(Size size)
Definition: mcxt.c:949
SysScanDesc systable_beginscan_ordered(Relation heapRelation, Relation indexRelation, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:565
#define elog(elevel,...)
Definition: elog.h:228
#define SET_VARSIZE_COMPRESSED(PTR, len)
Definition: postgres.h:331
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer)
Definition: detoast.h:22
Definition: c.h:556
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
int16 AttrNumber
Definition: attnum.h:21
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define BTGreaterEqualStrategyNumber
Definition: stratnum.h:32

◆ toast_raw_datum_size()

Size toast_raw_datum_size ( Datum  value)

Definition at line 806 of file detoast.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(), build_sorted_items(), byteaeq(), byteane(), byteaoctetlen(), compute_array_stats(), compute_distinct_stats(), compute_scalar_stats(), datum_image_eq(), record_image_cmp(), text_length(), text_starts_with(), texteq(), textne(), textoctetlen(), and toast_raw_datum_size().

807 {
808  struct varlena *attr = (struct varlena *) DatumGetPointer(value);
809  Size result;
810 
811  if (VARATT_IS_EXTERNAL_ONDISK(attr))
812  {
813  /* va_rawsize is the size of the original datum -- including header */
814  struct varatt_external toast_pointer;
815 
816  VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
817  result = toast_pointer.va_rawsize;
818  }
819  else if (VARATT_IS_EXTERNAL_INDIRECT(attr))
820  {
821  struct varatt_indirect toast_pointer;
822 
823  VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
824 
825  /* nested indirect Datums aren't allowed */
826  Assert(!VARATT_IS_EXTERNAL_INDIRECT(toast_pointer.pointer));
827 
828  return toast_raw_datum_size(PointerGetDatum(toast_pointer.pointer));
829  }
830  else if (VARATT_IS_EXTERNAL_EXPANDED(attr))
831  {
833  }
834  else if (VARATT_IS_COMPRESSED(attr))
835  {
836  /* here, va_rawsize is just the payload size */
837  result = VARRAWSIZE_4B_C(attr) + VARHDRSZ;
838  }
839  else if (VARATT_IS_SHORT(attr))
840  {
841  /*
842  * we have to normalize the header length to VARHDRSZ or else the
843  * callers of this function will be confused.
844  */
845  result = VARSIZE_SHORT(attr) - VARHDRSZ_SHORT + VARHDRSZ;
846  }
847  else
848  {
849  /* plain untoasted datum */
850  result = VARSIZE(attr);
851  }
852  return result;
853 }
#define VARATT_IS_EXTERNAL_ONDISK(PTR)
Definition: postgres.h:314
#define VARATT_IS_COMPRESSED(PTR)
Definition: postgres.h:312
#define VARATT_IS_EXTERNAL_EXPANDED(PTR)
Definition: postgres.h:322
#define VARHDRSZ_SHORT
Definition: postgres.h:268
#define VARSIZE(PTR)
Definition: postgres.h:303
#define VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr)
Definition: detoast.h:32
#define PointerGetDatum(X)
Definition: postgres.h:556
#define VARHDRSZ
Definition: c.h:562
static struct @145 value
#define VARATT_IS_EXTERNAL_INDIRECT(PTR)
Definition: postgres.h:316
#define VARATT_IS_SHORT(PTR)
Definition: postgres.h:326
Size EOH_get_flat_size(ExpandedObjectHeader *eohptr)
Definition: expandeddatum.c:75
Size toast_raw_datum_size(Datum value)
Definition: detoast.c:806
#define VARSIZE_SHORT(PTR)
Definition: postgres.h:305
ExpandedObjectHeader * DatumGetEOHP(Datum d)
Definition: expandeddatum.c:29
#define VARRAWSIZE_4B_C(PTR)
Definition: postgres.h:283
#define Assert(condition)
Definition: c.h:739
size_t Size
Definition: c.h:467
#define DatumGetPointer(X)
Definition: postgres.h:549
Definition: c.h:556