PostgreSQL Source Code  git master
detoast.c File Reference
#include "postgres.h"
#include "access/detoast.h"
#include "access/table.h"
#include "access/tableam.h"
#include "access/toast_internals.h"
#include "common/pg_lzcompress.h"
#include "utils/expandeddatum.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 slicelength)
 
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 115 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().

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

◆ detoast_attr_slice()

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

Definition at line 203 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().

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

◆ detoast_external_attr()

struct varlena* detoast_external_attr ( struct varlena attr)

Definition at line 44 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().

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

◆ toast_datum_size()

Size toast_datum_size ( Datum  value)

Definition at line 557 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().

558 {
559  struct varlena *attr = (struct varlena *) DatumGetPointer(value);
560  Size result;
561 
562  if (VARATT_IS_EXTERNAL_ONDISK(attr))
563  {
564  /*
565  * Attribute is stored externally - return the extsize whether
566  * compressed or not. We do not count the size of the toast pointer
567  * ... should we?
568  */
569  struct varatt_external toast_pointer;
570 
571  VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
572  result = toast_pointer.va_extsize;
573  }
574  else if (VARATT_IS_EXTERNAL_INDIRECT(attr))
575  {
576  struct varatt_indirect toast_pointer;
577 
578  VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
579 
580  /* nested indirect Datums aren't allowed */
582 
583  return toast_datum_size(PointerGetDatum(toast_pointer.pointer));
584  }
585  else if (VARATT_IS_EXTERNAL_EXPANDED(attr))
586  {
588  }
589  else if (VARATT_IS_SHORT(attr))
590  {
591  result = VARSIZE_SHORT(attr);
592  }
593  else
594  {
595  /*
596  * Attribute is stored inline either compressed or not, just calculate
597  * the size of the datum in either case.
598  */
599  result = VARSIZE(attr);
600  }
601  return result;
602 }
#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
Size toast_datum_size(Datum value)
Definition: detoast.c:557
#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
static struct @143 value
#define Assert(condition)
Definition: c.h:738
size_t Size
Definition: c.h:466
#define DatumGetPointer(X)
Definition: postgres.h:549
Definition: c.h:555

◆ toast_decompress_datum()

static struct varlena * toast_decompress_datum ( struct varlena attr)
static

Definition at line 445 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().

446 {
447  struct varlena *result;
448 
450 
451  result = (struct varlena *)
454 
456  TOAST_COMPRESS_SIZE(attr),
457  VARDATA(result),
458  TOAST_COMPRESS_RAWSIZE(attr), true) < 0)
459  elog(ERROR, "compressed data is corrupted");
460 
461  return result;
462 }
#define VARATT_IS_COMPRESSED(PTR)
Definition: postgres.h:312
#define VARDATA(PTR)
Definition: postgres.h:302
#define VARHDRSZ
Definition: c.h:561
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:738
void * palloc(Size size)
Definition: mcxt.c:949
#define elog(elevel,...)
Definition: elog.h:214
Definition: c.h:555
#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 473 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().

474 {
475  struct varlena *result;
476  int32 rawsize;
477 
479 
480  result = (struct varlena *) palloc(slicelength + VARHDRSZ);
481 
482  rawsize = pglz_decompress(TOAST_COMPRESS_RAWDATA(attr),
484  VARDATA(result),
485  slicelength, false);
486  if (rawsize < 0)
487  elog(ERROR, "compressed data is corrupted");
488 
489  SET_VARSIZE(result, rawsize + VARHDRSZ);
490  return result;
491 }
#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:561
int32 pglz_decompress(const char *source, int32 slen, char *dest, int32 rawsize, bool check_complete)
signed int int32
Definition: c.h:355
#define ERROR
Definition: elog.h:43
#define TOAST_COMPRESS_RAWDATA(ptr)
#define Assert(condition)
Definition: c.h:738
#define TOAST_COMPRESS_HDRSZ
void * palloc(Size size)
Definition: mcxt.c:949
#define elog(elevel,...)
Definition: elog.h:214
Definition: c.h:555
#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 323 of file detoast.c.

References AccessShareLock, elog, ERROR, palloc(), SET_VARSIZE, SET_VARSIZE_COMPRESSED, table_close(), table_open(), table_relation_fetch_toast_slice(), varatt_external::va_extsize, varatt_external::va_toastrelid, varatt_external::va_valueid, VARATT_EXTERNAL_GET_POINTER, VARATT_EXTERNAL_IS_COMPRESSED, VARATT_IS_EXTERNAL_ONDISK, and VARHDRSZ.

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

324 {
325  Relation toastrel;
326  struct varlena *result;
327  struct varatt_external toast_pointer;
328  int32 attrsize;
329 
330  if (!VARATT_IS_EXTERNAL_ONDISK(attr))
331  elog(ERROR, "toast_fetch_datum shouldn't be called for non-ondisk datums");
332 
333  /* Must copy to access aligned fields */
334  VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
335 
336  attrsize = toast_pointer.va_extsize;
337 
338  result = (struct varlena *) palloc(attrsize + VARHDRSZ);
339 
340  if (VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer))
341  SET_VARSIZE_COMPRESSED(result, attrsize + VARHDRSZ);
342  else
343  SET_VARSIZE(result, attrsize + VARHDRSZ);
344 
345  if (attrsize == 0)
346  return result; /* Probably shouldn't happen, but just in case. */
347 
348  /*
349  * Open the toast relation and its indexes
350  */
351  toastrel = table_open(toast_pointer.va_toastrelid, AccessShareLock);
352 
353  /* Fetch all chunks */
354  table_relation_fetch_toast_slice(toastrel, toast_pointer.va_valueid,
355  attrsize, 0, attrsize, result);
356 
357  /* Close toast table */
358  table_close(toastrel, AccessShareLock);
359 
360  return result;
361 }
#define VARATT_IS_EXTERNAL_ONDISK(PTR)
Definition: postgres.h:314
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr)
Definition: detoast.h:32
#define VARHDRSZ
Definition: c.h:561
static void table_relation_fetch_toast_slice(Relation toastrel, Oid valueid, int32 attrsize, int32 sliceoffset, int32 slicelength, struct varlena *result)
Definition: tableam.h:1672
#define AccessShareLock
Definition: lockdefs.h:36
signed int int32
Definition: c.h:355
#define ERROR
Definition: elog.h:43
void * palloc(Size size)
Definition: mcxt.c:949
#define elog(elevel,...)
Definition: elog.h:214
#define SET_VARSIZE_COMPRESSED(PTR, len)
Definition: postgres.h:331
#define VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer)
Definition: detoast.h:22
Definition: c.h:555
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ toast_fetch_datum_slice()

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

Definition at line 375 of file detoast.c.

References AccessShareLock, Assert, elog, ERROR, palloc(), SET_VARSIZE, SET_VARSIZE_COMPRESSED, table_close(), table_open(), table_relation_fetch_toast_slice(), varatt_external::va_extsize, varatt_external::va_toastrelid, varatt_external::va_valueid, VARATT_EXTERNAL_GET_POINTER, VARATT_EXTERNAL_IS_COMPRESSED, VARATT_IS_EXTERNAL_ONDISK, and VARHDRSZ.

Referenced by detoast_attr_slice().

377 {
378  Relation toastrel;
379  struct varlena *result;
380  struct varatt_external toast_pointer;
381  int32 attrsize;
382 
383  if (!VARATT_IS_EXTERNAL_ONDISK(attr))
384  elog(ERROR, "toast_fetch_datum_slice shouldn't be called for non-ondisk datums");
385 
386  /* Must copy to access aligned fields */
387  VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
388 
389  /*
390  * It's nonsense to fetch slices of a compressed datum unless when it's
391  * a prefix -- this isn't lo_* we can't return a compressed datum which
392  * is meaningful to toast later.
393  */
394  Assert(!VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer) || 0 == sliceoffset);
395 
396  attrsize = toast_pointer.va_extsize;
397 
398  if (sliceoffset >= attrsize)
399  {
400  sliceoffset = 0;
401  slicelength = 0;
402  }
403 
404  /*
405  * When fetching a prefix of a compressed external datum, account for the
406  * rawsize tracking amount of raw data, which is stored at the beginning
407  * as an int32 value).
408  */
409  if (VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer) && slicelength > 0)
410  slicelength = slicelength + sizeof(int32);
411 
412  if (((sliceoffset + slicelength) > attrsize) || slicelength < 0)
413  slicelength = attrsize - sliceoffset;
414 
415  result = (struct varlena *) palloc(slicelength + VARHDRSZ);
416 
417  if (VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer))
418  SET_VARSIZE_COMPRESSED(result, slicelength + VARHDRSZ);
419  else
420  SET_VARSIZE(result, slicelength + VARHDRSZ);
421 
422  if (slicelength == 0)
423  return result; /* Can save a lot of work at this point! */
424 
425  /* Open the toast relation */
426  toastrel = table_open(toast_pointer.va_toastrelid, AccessShareLock);
427 
428  /* Fetch all chunks */
429  table_relation_fetch_toast_slice(toastrel, toast_pointer.va_valueid,
430  attrsize, sliceoffset, slicelength,
431  result);
432 
433  /* Close toast table */
434  table_close(toastrel, AccessShareLock);
435 
436  return result;
437 }
#define VARATT_IS_EXTERNAL_ONDISK(PTR)
Definition: postgres.h:314
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr)
Definition: detoast.h:32
#define VARHDRSZ
Definition: c.h:561
static void table_relation_fetch_toast_slice(Relation toastrel, Oid valueid, int32 attrsize, int32 sliceoffset, int32 slicelength, struct varlena *result)
Definition: tableam.h:1672
#define AccessShareLock
Definition: lockdefs.h:36
signed int int32
Definition: c.h:355
#define ERROR
Definition: elog.h:43
#define Assert(condition)
Definition: c.h:738
void * palloc(Size size)
Definition: mcxt.c:949
#define elog(elevel,...)
Definition: elog.h:214
#define SET_VARSIZE_COMPRESSED(PTR, len)
Definition: postgres.h:331
#define VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer)
Definition: detoast.h:22
Definition: c.h:555
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ toast_raw_datum_size()

Size toast_raw_datum_size ( Datum  value)

Definition at line 501 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().

502 {
503  struct varlena *attr = (struct varlena *) DatumGetPointer(value);
504  Size result;
505 
506  if (VARATT_IS_EXTERNAL_ONDISK(attr))
507  {
508  /* va_rawsize is the size of the original datum -- including header */
509  struct varatt_external toast_pointer;
510 
511  VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
512  result = toast_pointer.va_rawsize;
513  }
514  else if (VARATT_IS_EXTERNAL_INDIRECT(attr))
515  {
516  struct varatt_indirect toast_pointer;
517 
518  VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
519 
520  /* nested indirect Datums aren't allowed */
521  Assert(!VARATT_IS_EXTERNAL_INDIRECT(toast_pointer.pointer));
522 
523  return toast_raw_datum_size(PointerGetDatum(toast_pointer.pointer));
524  }
525  else if (VARATT_IS_EXTERNAL_EXPANDED(attr))
526  {
528  }
529  else if (VARATT_IS_COMPRESSED(attr))
530  {
531  /* here, va_rawsize is just the payload size */
532  result = VARRAWSIZE_4B_C(attr) + VARHDRSZ;
533  }
534  else if (VARATT_IS_SHORT(attr))
535  {
536  /*
537  * we have to normalize the header length to VARHDRSZ or else the
538  * callers of this function will be confused.
539  */
540  result = VARSIZE_SHORT(attr) - VARHDRSZ_SHORT + VARHDRSZ;
541  }
542  else
543  {
544  /* plain untoasted datum */
545  result = VARSIZE(attr);
546  }
547  return result;
548 }
#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:561
#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:501
#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
static struct @143 value
#define Assert(condition)
Definition: c.h:738
size_t Size
Definition: c.h:466
#define DatumGetPointer(X)
Definition: postgres.h:549
Definition: c.h:555