PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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

#define EXTERN_TUPLE_MAX_SIZE   MaximumBytesPerTuple(EXTERN_TUPLES_PER_PAGE)

Definition at line 89 of file tuptoaster.h.

#define EXTERN_TUPLES_PER_PAGE   4 /* tweak only this */

Definition at line 87 of file tuptoaster.h.

#define INDIRECT_POINTER_SIZE   (VARHDRSZ_EXTERNAL + sizeof(varatt_indirect))

Definition at line 102 of file tuptoaster.h.

Referenced by make_tuple_indirect(), and ReorderBufferToastReplace().

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

Definition at line 30 of file tuptoaster.h.

#define TOAST_INDEX_HACK

Definition at line 24 of file tuptoaster.h.

Referenced by index_form_tuple().

#define TOAST_INDEX_TARGET   (MaxHeapTupleSize / 16)

Definition at line 75 of file tuptoaster.h.

Referenced by gtsvector_compress(), and index_form_tuple().

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

Definition at line 91 of file tuptoaster.h.

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

#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().

#define TOAST_TUPLE_TARGET   TOAST_TUPLE_THRESHOLD

Definition at line 57 of file tuptoaster.h.

Referenced by toast_insert_or_update().

#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().

#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().

#define TOAST_TUPLES_PER_PAGE   4

Definition at line 53 of file tuptoaster.h.

#define TOAST_TUPLES_PER_PAGE_MAIN   1

Definition at line 66 of file tuptoaster.h.

#define VARATT_EXTERNAL_GET_POINTER (   toast_pointer,
  attr 
)
Value:
do { \
varattrib_1b_e *attre = (varattrib_1b_e *) (attr); \
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 Assert(condition)
Definition: c.h:675
#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().

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

Function Documentation

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, result, 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
return result
Definition: formatting.c:1632
#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:675
#define VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr)
Definition: tuptoaster.h:121
static struct varlena * toast_fetch_datum(struct varlena *attr)
Definition: tuptoaster.c:1876
size_t Size
Definition: c.h:356
void * palloc(Size size)
Definition: mcxt.c:849
Definition: c.h:439
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, result, 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:445
return result
Definition: formatting.c:1632
struct varlena * heap_tuple_untoast_attr(struct varlena *attr)
Definition: tuptoaster.c:172
void pfree(void *pointer)
Definition: mcxt.c:950
#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:675
#define VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr)
Definition: tuptoaster.h:121
static struct varlena * toast_fetch_datum(struct varlena *attr)
Definition: tuptoaster.c:1876
size_t Size
Definition: c.h:356
static struct varlena * toast_decompress_datum(struct varlena *attr)
Definition: tuptoaster.c:2279
#define VARATT_IS_EXTENDED(PTR)
Definition: postgres.h:326
#define VARDATA_SHORT(PTR)
Definition: postgres.h:307
void * palloc(Size size)
Definition: mcxt.c:849
Definition: c.h:439
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:328
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, result, 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:2047
#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:445
return result
Definition: formatting.c:1632
signed int int32
Definition: c.h:256
#define VARATT_IS_EXTERNAL(PTR)
Definition: postgres.h:314
void pfree(void *pointer)
Definition: mcxt.c:950
#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:675
#define VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr)
Definition: tuptoaster.h:121
static struct varlena * toast_fetch_datum(struct varlena *attr)
Definition: tuptoaster.c:1876
static struct varlena * toast_decompress_datum(struct varlena *attr)
Definition: tuptoaster.c:2279
#define VARDATA_SHORT(PTR)
Definition: postgres.h:307
void * palloc(Size size)
Definition: mcxt.c:849
Definition: c.h:439
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:328
HeapTuple toast_build_flattened_tuple ( TupleDesc  tupleDesc,
Datum values,
bool isnull 
)

Definition at line 1305 of file tuptoaster.c.

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

Referenced by ExecEvalWholeRowVar().

1308 {
1309  HeapTuple new_tuple;
1310  Form_pg_attribute *att = tupleDesc->attrs;
1311  int numAttrs = tupleDesc->natts;
1312  int num_to_free;
1313  int i;
1314  Datum new_values[MaxTupleAttributeNumber];
1315  Pointer freeable_values[MaxTupleAttributeNumber];
1316 
1317  /*
1318  * We can pass the caller's isnull array directly to heap_form_tuple, but
1319  * we potentially need to modify the values array.
1320  */
1321  Assert(numAttrs <= MaxTupleAttributeNumber);
1322  memcpy(new_values, values, numAttrs * sizeof(Datum));
1323 
1324  num_to_free = 0;
1325  for (i = 0; i < numAttrs; i++)
1326  {
1327  /*
1328  * Look at non-null varlena attributes
1329  */
1330  if (!isnull[i] && att[i]->attlen == -1)
1331  {
1332  struct varlena *new_value;
1333 
1334  new_value = (struct varlena *) DatumGetPointer(new_values[i]);
1335  if (VARATT_IS_EXTERNAL(new_value))
1336  {
1337  new_value = heap_tuple_fetch_attr(new_value);
1338  new_values[i] = PointerGetDatum(new_value);
1339  freeable_values[num_to_free++] = (Pointer) new_value;
1340  }
1341  }
1342  }
1343 
1344  /*
1345  * Form the reconfigured tuple.
1346  */
1347  new_tuple = heap_form_tuple(tupleDesc, new_values, isnull);
1348 
1349  /*
1350  * Free allocated temp values
1351  */
1352  for (i = 0; i < num_to_free; i++)
1353  pfree(freeable_values[i]);
1354 
1355  return new_tuple;
1356 }
#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
Form_pg_attribute * attrs
Definition: tupdesc.h:74
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
int natts
Definition: tupdesc.h:73
#define VARATT_IS_EXTERNAL(PTR)
Definition: postgres.h:314
void pfree(void *pointer)
Definition: mcxt.c:950
char * Pointer
Definition: c.h:245
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
uintptr_t Datum
Definition: postgres.h:372
#define Assert(condition)
Definition: c.h:675
#define DatumGetPointer(X)
Definition: postgres.h:555
static Datum values[MAXATTR]
Definition: bootstrap.c:163
int i
Definition: c.h:439
Datum toast_compress_datum ( Datum  value)

Definition at line 1373 of file tuptoaster.c.

References Assert, DatumGetPointer, PGLZ_Strategy::max_input_size, NULL, 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().

1374 {
1375  struct varlena *tmp;
1377  int32 len;
1378 
1381 
1382  /*
1383  * No point in wasting a palloc cycle if value size is out of the allowed
1384  * range for compression
1385  */
1386  if (valsize < PGLZ_strategy_default->min_input_size ||
1388  return PointerGetDatum(NULL);
1389 
1390  tmp = (struct varlena *) palloc(PGLZ_MAX_OUTPUT(valsize) +
1392 
1393  /*
1394  * We recheck the actual size even if pglz_compress() reports success,
1395  * because it might be satisfied with having saved as little as one byte
1396  * in the compressed data --- which could turn into a net loss once you
1397  * consider header and alignment padding. Worst case, the compressed
1398  * format might require three padding bytes (plus header, which is
1399  * included in VARSIZE(tmp)), whereas the uncompressed format would take
1400  * only one header byte and no padding if the value is short enough. So
1401  * we insist on a savings of more than 2 bytes to ensure we have a gain.
1402  */
1404  valsize,
1407  if (len >= 0 &&
1408  len + TOAST_COMPRESS_HDRSZ < valsize - 2)
1409  {
1410  TOAST_COMPRESS_SET_RAWSIZE(tmp, valsize);
1412  /* successful compression */
1413  return PointerGetDatum(tmp);
1414  }
1415  else
1416  {
1417  /* incompressible data */
1418  pfree(tmp);
1419  return PointerGetDatum(NULL);
1420  }
1421 }
#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:256
#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:950
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 NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
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:849
#define TOAST_COMPRESS_RAWDATA(ptr)
Definition: tuptoaster.c:65
#define SET_VARSIZE_COMPRESSED(PTR, len)
Definition: postgres.h:330
Definition: c.h:439
const PGLZ_Strategy *const PGLZ_strategy_default
static struct @121 value
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, result, 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
return result
Definition: formatting.c:1632
#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
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:675
#define VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr)
Definition: tuptoaster.h:121
size_t Size
Definition: c.h:356
#define DatumGetPointer(X)
Definition: postgres.h:555
Definition: c.h:439
static struct @121 value
void toast_delete ( Relation  rel,
HeapTuple  oldtup,
bool  is_speculative 
)

Definition at line 464 of file tuptoaster.c.

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

Referenced by heap_abort_speculative(), and heap_delete().

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

Definition at line 1084 of file tuptoaster.c.

References Assert, tupleDesc::attrs, 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, and VARATT_IS_EXTERNAL.

Referenced by CatalogCacheCreateEntry(), and ExtractReplicaIdentity().

1085 {
1086  HeapTuple new_tuple;
1087  Form_pg_attribute *att = tupleDesc->attrs;
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] && att[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:79
#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
Form_pg_attribute * attrs
Definition: tupdesc.h:74
#define HEAP2_XACT_MASK
Definition: htup_details.h:269
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
int natts
Definition: tupdesc.h:73
HeapTupleHeader t_data
Definition: htup.h:67
#define HeapTupleSetOid(tuple, oid)
Definition: htup_details.h:698
#define VARATT_IS_EXTERNAL(PTR)
Definition: postgres.h:314
void pfree(void *pointer)
Definition: mcxt.c:950
ItemPointerData t_ctid
Definition: htup_details.h:150
ItemPointerData t_self
Definition: htup.h:65
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
Oid t_tableOid
Definition: htup.h:66
uintptr_t Datum
Definition: postgres.h:372
#define Assert(condition)
Definition: c.h:675
#define DatumGetPointer(X)
Definition: postgres.h:555
void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)
Definition: heaptuple.c:933
int i
Definition: c.h:439
#define HEAP_XACT_MASK
Definition: htup_details.h:204
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
Datum toast_flatten_tuple_to_datum ( HeapTupleHeader  tup,
uint32  tup_len,
TupleDesc  tupleDesc 
)

Definition at line 1187 of file tuptoaster.c.

References Assert, tupleDesc::attrs, 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, NULL, 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, 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  Form_pg_attribute *att = tupleDesc->attrs;
1197  int numAttrs = tupleDesc->natts;
1198  int i;
1199  bool has_nulls = false;
1200  Datum toast_values[MaxTupleAttributeNumber];
1201  bool toast_isnull[MaxTupleAttributeNumber];
1202  bool toast_free[MaxTupleAttributeNumber];
1203 
1204  /* Build a temporary HeapTuple control structure */
1205  tmptup.t_len = tup_len;
1206  ItemPointerSetInvalid(&(tmptup.t_self));
1207  tmptup.t_tableOid = InvalidOid;
1208  tmptup.t_data = tup;
1209 
1210  /*
1211  * Break down the tuple into fields.
1212  */
1213  Assert(numAttrs <= MaxTupleAttributeNumber);
1214  heap_deform_tuple(&tmptup, tupleDesc, toast_values, toast_isnull);
1215 
1216  memset(toast_free, 0, numAttrs * sizeof(bool));
1217 
1218  for (i = 0; i < numAttrs; i++)
1219  {
1220  /*
1221  * Look at non-null varlena attributes
1222  */
1223  if (toast_isnull[i])
1224  has_nulls = true;
1225  else if (att[i]->attlen == -1)
1226  {
1227  struct varlena *new_value;
1228 
1229  new_value = (struct varlena *) DatumGetPointer(toast_values[i]);
1230  if (VARATT_IS_EXTERNAL(new_value) ||
1231  VARATT_IS_COMPRESSED(new_value))
1232  {
1233  new_value = heap_tuple_untoast_attr(new_value);
1234  toast_values[i] = PointerGetDatum(new_value);
1235  toast_free[i] = true;
1236  }
1237  }
1238  }
1239 
1240  /*
1241  * Calculate the new size of the tuple.
1242  *
1243  * This should match the reconstruction code in toast_insert_or_update.
1244  */
1245  new_header_len = SizeofHeapTupleHeader;
1246  if (has_nulls)
1247  new_header_len += BITMAPLEN(numAttrs);
1248  if (tup->t_infomask & HEAP_HASOID)
1249  new_header_len += sizeof(Oid);
1250  new_header_len = MAXALIGN(new_header_len);
1251  new_data_len = heap_compute_data_size(tupleDesc,
1252  toast_values, toast_isnull);
1253  new_tuple_len = new_header_len + new_data_len;
1254 
1255  new_data = (HeapTupleHeader) palloc0(new_tuple_len);
1256 
1257  /*
1258  * Copy the existing tuple header, but adjust natts and t_hoff.
1259  */
1260  memcpy(new_data, tup, SizeofHeapTupleHeader);
1261  HeapTupleHeaderSetNatts(new_data, numAttrs);
1262  new_data->t_hoff = new_header_len;
1263  if (tup->t_infomask & HEAP_HASOID)
1265 
1266  /* Set the composite-Datum header fields correctly */
1267  HeapTupleHeaderSetDatumLength(new_data, new_tuple_len);
1268  HeapTupleHeaderSetTypeId(new_data, tupleDesc->tdtypeid);
1269  HeapTupleHeaderSetTypMod(new_data, tupleDesc->tdtypmod);
1270 
1271  /* Copy over the data, and fill the null bitmap if needed */
1272  heap_fill_tuple(tupleDesc,
1273  toast_values,
1274  toast_isnull,
1275  (char *) new_data + new_header_len,
1276  new_data_len,
1277  &(new_data->t_infomask),
1278  has_nulls ? new_data->t_bits : NULL);
1279 
1280  /*
1281  * Free allocated temp values
1282  */
1283  for (i = 0; i < numAttrs; i++)
1284  if (toast_free[i])
1285  pfree(DatumGetPointer(toast_values[i]));
1286 
1287  return PointerGetDatum(new_data);
1288 }
#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:146
#define SizeofHeapTupleHeader
Definition: htup_details.h:170
Oid tdtypeid
Definition: tupdesc.h:77
#define HeapTupleHeaderSetTypeId(tup, typeid)
Definition: htup_details.h:450
bits8 t_bits[FLEXIBLE_ARRAY_MEMBER]
Definition: htup_details.h:163
#define MaxTupleAttributeNumber
Definition: htup_details.h:33
#define PointerGetDatum(X)
Definition: postgres.h:562
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
Form_pg_attribute * attrs
Definition: tupdesc.h:74
#define BITMAPLEN(NATTS)
Definition: htup_details.h:548
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:73
int32 tdtypmod
Definition: tupdesc.h:78
signed int int32
Definition: c.h:256
#define HeapTupleHeaderSetDatumLength(tup, len)
Definition: htup_details.h:442
HeapTupleHeader t_data
Definition: htup.h:67
#define VARATT_IS_EXTERNAL(PTR)
Definition: postgres.h:314
void pfree(void *pointer)
Definition: mcxt.c:950
#define HeapTupleHeaderSetOid(tup, oid)
Definition: htup_details.h:473
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:878
uintptr_t Datum
Definition: postgres.h:372
#define HeapTupleHeaderSetTypMod(tup, typmod)
Definition: htup_details.h:460
#define InvalidOid
Definition: postgres_ext.h:36
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define HeapTupleHeaderSetNatts(tup, natts)
Definition: htup_details.h:535
#define MAXALIGN(LEN)
Definition: c.h:588
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:933
#define HeapTupleHeaderGetOid(tup)
Definition: htup_details.h:465
#define ItemPointerSetInvalid(pointer)
Definition: itemptr.h:149
int i
#define HEAP_HASOID
Definition: htup_details.h:178
Definition: c.h:439
Oid toast_get_valid_index ( Oid  toastoid,
LOCKMODE  lock 
)

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

1432 {
1433  int num_indexes;
1434  int validIndex;
1435  Oid validIndexOid;
1436  Relation *toastidxs;
1437  Relation toastrel;
1438 
1439  /* Open the toast relation */
1440  toastrel = heap_open(toastoid, lock);
1441 
1442  /* Look for the valid index of the toast relation */
1443  validIndex = toast_open_indexes(toastrel,
1444  lock,
1445  &toastidxs,
1446  &num_indexes);
1447  validIndexOid = RelationGetRelid(toastidxs[validIndex]);
1448 
1449  /* Close the toast relation and all its indexes */
1450  toast_close_indexes(toastidxs, num_indexes, lock);
1451  heap_close(toastrel, lock);
1452 
1453  return validIndexOid;
1454 }
static int toast_open_indexes(Relation toastrel, LOCKMODE lock, Relation **toastidxs, int *num_indexes)
Definition: tuptoaster.c:2308
static void toast_close_indexes(Relation *toastidxs, int num_indexes, LOCKMODE lock)
Definition: tuptoaster.c:2367
#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:1284
#define RelationGetRelid(relation)
Definition: rel.h:417
HeapTuple toast_insert_or_update ( Relation  rel,
HeapTuple  newtup,
HeapTuple  oldtup,
int  options 
)

Definition at line 536 of file tuptoaster.c.

References Assert, tupleDesc::attrs, 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, NULL, palloc0(), pfree(), PointerGetDatum, RelationData::rd_att, RelationData::rd_rel, 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, 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().

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