PostgreSQL Source Code  git master
heaptuple.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * heaptuple.c
4  * This file contains heap tuple accessor and mutator routines, as well
5  * as various tuple utilities.
6  *
7  * Some notes about varlenas and this code:
8  *
9  * Before Postgres 8.3 varlenas always had a 4-byte length header, and
10  * therefore always needed 4-byte alignment (at least). This wasted space
11  * for short varlenas, for example CHAR(1) took 5 bytes and could need up to
12  * 3 additional padding bytes for alignment.
13  *
14  * Now, a short varlena (up to 126 data bytes) is reduced to a 1-byte header
15  * and we don't align it. To hide this from datatype-specific functions that
16  * don't want to deal with it, such a datum is considered "toasted" and will
17  * be expanded back to the normal 4-byte-header format by pg_detoast_datum.
18  * (In performance-critical code paths we can use pg_detoast_datum_packed
19  * and the appropriate access macros to avoid that overhead.) Note that this
20  * conversion is performed directly in heap_form_tuple, without invoking
21  * heaptoast.c.
22  *
23  * This change will break any code that assumes it needn't detoast values
24  * that have been put into a tuple but never sent to disk. Hopefully there
25  * are few such places.
26  *
27  * Varlenas still have alignment INT (or DOUBLE) in pg_type/pg_attribute, since
28  * that's the normal requirement for the untoasted format. But we ignore that
29  * for the 1-byte-header format. This means that the actual start position
30  * of a varlena datum may vary depending on which format it has. To determine
31  * what is stored, we have to require that alignment padding bytes be zero.
32  * (Postgres actually has always zeroed them, but now it's required!) Since
33  * the first byte of a 1-byte-header varlena can never be zero, we can examine
34  * the first byte after the previous datum to tell if it's a pad byte or the
35  * start of a 1-byte-header varlena.
36  *
37  * Note that while formerly we could rely on the first varlena column of a
38  * system catalog to be at the offset suggested by the C struct for the
39  * catalog, this is now risky: it's only safe if the preceding field is
40  * word-aligned, so that there will never be any padding.
41  *
42  * We don't pack varlenas whose attstorage is PLAIN, since the data type
43  * isn't expecting to have to detoast values. This is used in particular
44  * by oidvector and int2vector, which are used in the system catalogs
45  * and we'd like to still refer to them via C struct offsets.
46  *
47  *
48  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
49  * Portions Copyright (c) 1994, Regents of the University of California
50  *
51  *
52  * IDENTIFICATION
53  * src/backend/access/common/heaptuple.c
54  *
55  *-------------------------------------------------------------------------
56  */
57 
58 #include "postgres.h"
59 
60 #include "access/heaptoast.h"
61 #include "access/sysattr.h"
62 #include "access/tupdesc_details.h"
63 #include "executor/tuptable.h"
64 #include "utils/expandeddatum.h"
65 
66 
67 /* Does att's datatype allow packing into the 1-byte-header varlena format? */
68 #define ATT_IS_PACKABLE(att) \
69  ((att)->attlen == -1 && (att)->attstorage != TYPSTORAGE_PLAIN)
70 /* Use this if it's already known varlena */
71 #define VARLENA_ATT_IS_PACKABLE(att) \
72  ((att)->attstorage != TYPSTORAGE_PLAIN)
73 
74 
75 /* ----------------------------------------------------------------
76  * misc support routines
77  * ----------------------------------------------------------------
78  */
79 
80 /*
81  * Return the missing value of an attribute, or NULL if there isn't one.
82  */
83 Datum
85  int attnum, bool *isnull)
86 {
88 
89  Assert(attnum <= tupleDesc->natts);
90  Assert(attnum > 0);
91 
92  att = TupleDescAttr(tupleDesc, attnum - 1);
93 
94  if (att->atthasmissing)
95  {
96  AttrMissing *attrmiss;
97 
98  Assert(tupleDesc->constr);
99  Assert(tupleDesc->constr->missing);
100 
101  attrmiss = tupleDesc->constr->missing + (attnum - 1);
102 
103  if (attrmiss->am_present)
104  {
105  *isnull = false;
106  return attrmiss->am_value;
107  }
108  }
109 
110  *isnull = true;
111  return PointerGetDatum(NULL);
112 }
113 
114 /*
115  * heap_compute_data_size
116  * Determine size of the data area of a tuple to be constructed
117  */
118 Size
120  Datum *values,
121  bool *isnull)
122 {
123  Size data_length = 0;
124  int i;
125  int numberOfAttributes = tupleDesc->natts;
126 
127  for (i = 0; i < numberOfAttributes; i++)
128  {
129  Datum val;
130  Form_pg_attribute atti;
131 
132  if (isnull[i])
133  continue;
134 
135  val = values[i];
136  atti = TupleDescAttr(tupleDesc, i);
137 
138  if (ATT_IS_PACKABLE(atti) &&
140  {
141  /*
142  * we're anticipating converting to a short varlena header, so
143  * adjust length and don't count any alignment
144  */
146  }
147  else if (atti->attlen == -1 &&
149  {
150  /*
151  * we want to flatten the expanded value so that the constructed
152  * tuple doesn't depend on it
153  */
154  data_length = att_align_nominal(data_length, atti->attalign);
155  data_length += EOH_get_flat_size(DatumGetEOHP(val));
156  }
157  else
158  {
159  data_length = att_align_datum(data_length, atti->attalign,
160  atti->attlen, val);
161  data_length = att_addlength_datum(data_length, atti->attlen,
162  val);
163  }
164  }
165 
166  return data_length;
167 }
168 
169 /*
170  * Per-attribute helper for heap_fill_tuple and other routines building tuples.
171  *
172  * Fill in either a data value or a bit in the null bitmask
173  */
174 static inline void
176  bits8 **bit,
177  int *bitmask,
178  char **dataP,
179  uint16 *infomask,
180  Datum datum,
181  bool isnull)
182 {
183  Size data_length;
184  char *data = *dataP;
185 
186  /*
187  * If we're building a null bitmap, set the appropriate bit for the
188  * current column value here.
189  */
190  if (bit != NULL)
191  {
192  if (*bitmask != HIGHBIT)
193  *bitmask <<= 1;
194  else
195  {
196  *bit += 1;
197  **bit = 0x0;
198  *bitmask = 1;
199  }
200 
201  if (isnull)
202  {
203  *infomask |= HEAP_HASNULL;
204  return;
205  }
206 
207  **bit |= *bitmask;
208  }
209 
210  /*
211  * XXX we use the att_align macros on the pointer value itself, not on an
212  * offset. This is a bit of a hack.
213  */
214  if (att->attbyval)
215  {
216  /* pass-by-value */
217  data = (char *) att_align_nominal(data, att->attalign);
218  store_att_byval(data, datum, att->attlen);
219  data_length = att->attlen;
220  }
221  else if (att->attlen == -1)
222  {
223  /* varlena */
224  Pointer val = DatumGetPointer(datum);
225 
226  *infomask |= HEAP_HASVARWIDTH;
227  if (VARATT_IS_EXTERNAL(val))
228  {
230  {
231  /*
232  * we want to flatten the expanded value so that the
233  * constructed tuple doesn't depend on it
234  */
235  ExpandedObjectHeader *eoh = DatumGetEOHP(datum);
236 
237  data = (char *) att_align_nominal(data,
238  att->attalign);
239  data_length = EOH_get_flat_size(eoh);
240  EOH_flatten_into(eoh, data, data_length);
241  }
242  else
243  {
244  *infomask |= HEAP_HASEXTERNAL;
245  /* no alignment, since it's short by definition */
246  data_length = VARSIZE_EXTERNAL(val);
247  memcpy(data, val, data_length);
248  }
249  }
250  else if (VARATT_IS_SHORT(val))
251  {
252  /* no alignment for short varlenas */
253  data_length = VARSIZE_SHORT(val);
254  memcpy(data, val, data_length);
255  }
256  else if (VARLENA_ATT_IS_PACKABLE(att) &&
258  {
259  /* convert to short varlena -- no alignment */
260  data_length = VARATT_CONVERTED_SHORT_SIZE(val);
261  SET_VARSIZE_SHORT(data, data_length);
262  memcpy(data + 1, VARDATA(val), data_length - 1);
263  }
264  else
265  {
266  /* full 4-byte header varlena */
267  data = (char *) att_align_nominal(data,
268  att->attalign);
269  data_length = VARSIZE(val);
270  memcpy(data, val, data_length);
271  }
272  }
273  else if (att->attlen == -2)
274  {
275  /* cstring ... never needs alignment */
276  *infomask |= HEAP_HASVARWIDTH;
277  Assert(att->attalign == TYPALIGN_CHAR);
278  data_length = strlen(DatumGetCString(datum)) + 1;
279  memcpy(data, DatumGetPointer(datum), data_length);
280  }
281  else
282  {
283  /* fixed-length pass-by-reference */
284  data = (char *) att_align_nominal(data, att->attalign);
285  Assert(att->attlen > 0);
286  data_length = att->attlen;
287  memcpy(data, DatumGetPointer(datum), data_length);
288  }
289 
290  data += data_length;
291  *dataP = data;
292 }
293 
294 /*
295  * heap_fill_tuple
296  * Load data portion of a tuple from values/isnull arrays
297  *
298  * We also fill the null bitmap (if any) and set the infomask bits
299  * that reflect the tuple's data contents.
300  *
301  * NOTE: it is now REQUIRED that the caller have pre-zeroed the data area.
302  */
303 void
305  Datum *values, bool *isnull,
306  char *data, Size data_size,
307  uint16 *infomask, bits8 *bit)
308 {
309  bits8 *bitP;
310  int bitmask;
311  int i;
312  int numberOfAttributes = tupleDesc->natts;
313 
314 #ifdef USE_ASSERT_CHECKING
315  char *start = data;
316 #endif
317 
318  if (bit != NULL)
319  {
320  bitP = &bit[-1];
321  bitmask = HIGHBIT;
322  }
323  else
324  {
325  /* just to keep compiler quiet */
326  bitP = NULL;
327  bitmask = 0;
328  }
329 
330  *infomask &= ~(HEAP_HASNULL | HEAP_HASVARWIDTH | HEAP_HASEXTERNAL);
331 
332  for (i = 0; i < numberOfAttributes; i++)
333  {
334  Form_pg_attribute attr = TupleDescAttr(tupleDesc, i);
335 
336  fill_val(attr,
337  bitP ? &bitP : NULL,
338  &bitmask,
339  &data,
340  infomask,
341  values ? values[i] : PointerGetDatum(NULL),
342  isnull ? isnull[i] : true);
343  }
344 
345  Assert((data - start) == data_size);
346 }
347 
348 
349 /* ----------------------------------------------------------------
350  * heap tuple interface
351  * ----------------------------------------------------------------
352  */
353 
354 /* ----------------
355  * heap_attisnull - returns true iff tuple attribute is not present
356  * ----------------
357  */
358 bool
360 {
361  /*
362  * We allow a NULL tupledesc for relations not expected to have missing
363  * values, such as catalog relations and indexes.
364  */
365  Assert(!tupleDesc || attnum <= tupleDesc->natts);
366  if (attnum > (int) HeapTupleHeaderGetNatts(tup->t_data))
367  {
368  if (tupleDesc && TupleDescAttr(tupleDesc, attnum - 1)->atthasmissing)
369  return false;
370  else
371  return true;
372  }
373 
374  if (attnum > 0)
375  {
376  if (HeapTupleNoNulls(tup))
377  return false;
378  return att_isnull(attnum - 1, tup->t_data->t_bits);
379  }
380 
381  switch (attnum)
382  {
389  /* these are never null */
390  break;
391 
392  default:
393  elog(ERROR, "invalid attnum: %d", attnum);
394  }
395 
396  return false;
397 }
398 
399 /* ----------------
400  * nocachegetattr
401  *
402  * This only gets called from fastgetattr() macro, in cases where
403  * we can't use a cacheoffset and the value is not null.
404  *
405  * This caches attribute offsets in the attribute descriptor.
406  *
407  * An alternative way to speed things up would be to cache offsets
408  * with the tuple, but that seems more difficult unless you take
409  * the storage hit of actually putting those offsets into the
410  * tuple you send to disk. Yuck.
411  *
412  * This scheme will be slightly slower than that, but should
413  * perform well for queries which hit large #'s of tuples. After
414  * you cache the offsets once, examining all the other tuples using
415  * the same attribute descriptor will go much quicker. -cim 5/4/91
416  *
417  * NOTE: if you need to change this code, see also heap_deform_tuple.
418  * Also see nocache_index_getattr, which is the same code for index
419  * tuples.
420  * ----------------
421  */
422 Datum
424  int attnum,
425  TupleDesc tupleDesc)
426 {
427  HeapTupleHeader td = tup->t_data;
428  char *tp; /* ptr to data part of tuple */
429  bits8 *bp = td->t_bits; /* ptr to null bitmap in tuple */
430  bool slow = false; /* do we have to walk attrs? */
431  int off; /* current offset within data */
432 
433  /* ----------------
434  * Three cases:
435  *
436  * 1: No nulls and no variable-width attributes.
437  * 2: Has a null or a var-width AFTER att.
438  * 3: Has nulls or var-widths BEFORE att.
439  * ----------------
440  */
441 
442  attnum--;
443 
444  if (!HeapTupleNoNulls(tup))
445  {
446  /*
447  * there's a null somewhere in the tuple
448  *
449  * check to see if any preceding bits are null...
450  */
451  int byte = attnum >> 3;
452  int finalbit = attnum & 0x07;
453 
454  /* check for nulls "before" final bit of last byte */
455  if ((~bp[byte]) & ((1 << finalbit) - 1))
456  slow = true;
457  else
458  {
459  /* check for nulls in any "earlier" bytes */
460  int i;
461 
462  for (i = 0; i < byte; i++)
463  {
464  if (bp[i] != 0xFF)
465  {
466  slow = true;
467  break;
468  }
469  }
470  }
471  }
472 
473  tp = (char *) td + td->t_hoff;
474 
475  if (!slow)
476  {
477  Form_pg_attribute att;
478 
479  /*
480  * If we get here, there are no nulls up to and including the target
481  * attribute. If we have a cached offset, we can use it.
482  */
483  att = TupleDescAttr(tupleDesc, attnum);
484  if (att->attcacheoff >= 0)
485  return fetchatt(att, tp + att->attcacheoff);
486 
487  /*
488  * Otherwise, check for non-fixed-length attrs up to and including
489  * target. If there aren't any, it's safe to cheaply initialize the
490  * cached offsets for these attrs.
491  */
492  if (HeapTupleHasVarWidth(tup))
493  {
494  int j;
495 
496  for (j = 0; j <= attnum; j++)
497  {
498  if (TupleDescAttr(tupleDesc, j)->attlen <= 0)
499  {
500  slow = true;
501  break;
502  }
503  }
504  }
505  }
506 
507  if (!slow)
508  {
509  int natts = tupleDesc->natts;
510  int j = 1;
511 
512  /*
513  * If we get here, we have a tuple with no nulls or var-widths up to
514  * and including the target attribute, so we can use the cached offset
515  * ... only we don't have it yet, or we'd not have got here. Since
516  * it's cheap to compute offsets for fixed-width columns, we take the
517  * opportunity to initialize the cached offsets for *all* the leading
518  * fixed-width columns, in hope of avoiding future visits to this
519  * routine.
520  */
521  TupleDescAttr(tupleDesc, 0)->attcacheoff = 0;
522 
523  /* we might have set some offsets in the slow path previously */
524  while (j < natts && TupleDescAttr(tupleDesc, j)->attcacheoff > 0)
525  j++;
526 
527  off = TupleDescAttr(tupleDesc, j - 1)->attcacheoff +
528  TupleDescAttr(tupleDesc, j - 1)->attlen;
529 
530  for (; j < natts; j++)
531  {
532  Form_pg_attribute att = TupleDescAttr(tupleDesc, j);
533 
534  if (att->attlen <= 0)
535  break;
536 
537  off = att_align_nominal(off, att->attalign);
538 
539  att->attcacheoff = off;
540 
541  off += att->attlen;
542  }
543 
544  Assert(j > attnum);
545 
546  off = TupleDescAttr(tupleDesc, attnum)->attcacheoff;
547  }
548  else
549  {
550  bool usecache = true;
551  int i;
552 
553  /*
554  * Now we know that we have to walk the tuple CAREFULLY. But we still
555  * might be able to cache some offsets for next time.
556  *
557  * Note - This loop is a little tricky. For each non-null attribute,
558  * we have to first account for alignment padding before the attr,
559  * then advance over the attr based on its length. Nulls have no
560  * storage and no alignment padding either. We can use/set
561  * attcacheoff until we reach either a null or a var-width attribute.
562  */
563  off = 0;
564  for (i = 0;; i++) /* loop exit is at "break" */
565  {
566  Form_pg_attribute att = TupleDescAttr(tupleDesc, i);
567 
568  if (HeapTupleHasNulls(tup) && att_isnull(i, bp))
569  {
570  usecache = false;
571  continue; /* this cannot be the target att */
572  }
573 
574  /* If we know the next offset, we can skip the rest */
575  if (usecache && att->attcacheoff >= 0)
576  off = att->attcacheoff;
577  else if (att->attlen == -1)
578  {
579  /*
580  * We can only cache the offset for a varlena attribute if the
581  * offset is already suitably aligned, so that there would be
582  * no pad bytes in any case: then the offset will be valid for
583  * either an aligned or unaligned value.
584  */
585  if (usecache &&
586  off == att_align_nominal(off, att->attalign))
587  att->attcacheoff = off;
588  else
589  {
590  off = att_align_pointer(off, att->attalign, -1,
591  tp + off);
592  usecache = false;
593  }
594  }
595  else
596  {
597  /* not varlena, so safe to use att_align_nominal */
598  off = att_align_nominal(off, att->attalign);
599 
600  if (usecache)
601  att->attcacheoff = off;
602  }
603 
604  if (i == attnum)
605  break;
606 
607  off = att_addlength_pointer(off, att->attlen, tp + off);
608 
609  if (usecache && att->attlen <= 0)
610  usecache = false;
611  }
612  }
613 
614  return fetchatt(TupleDescAttr(tupleDesc, attnum), tp + off);
615 }
616 
617 /* ----------------
618  * heap_getsysattr
619  *
620  * Fetch the value of a system attribute for a tuple.
621  *
622  * This is a support routine for the heap_getattr macro. The macro
623  * has already determined that the attnum refers to a system attribute.
624  * ----------------
625  */
626 Datum
627 heap_getsysattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
628 {
629  Datum result;
630 
631  Assert(tup);
632 
633  /* Currently, no sys attribute ever reads as NULL. */
634  *isnull = false;
635 
636  switch (attnum)
637  {
639  /* pass-by-reference datatype */
640  result = PointerGetDatum(&(tup->t_self));
641  break;
644  break;
647  break;
650 
651  /*
652  * cmin and cmax are now both aliases for the same field, which
653  * can in fact also be a combo command id. XXX perhaps we should
654  * return the "real" cmin or cmax if possible, that is if we are
655  * inside the originating transaction?
656  */
658  break;
660  result = ObjectIdGetDatum(tup->t_tableOid);
661  break;
662  default:
663  elog(ERROR, "invalid attnum: %d", attnum);
664  result = 0; /* keep compiler quiet */
665  break;
666  }
667  return result;
668 }
669 
670 /* ----------------
671  * heap_copytuple
672  *
673  * returns a copy of an entire tuple
674  *
675  * The HeapTuple struct, tuple header, and tuple data are all allocated
676  * as a single palloc() block.
677  * ----------------
678  */
679 HeapTuple
681 {
682  HeapTuple newTuple;
683 
684  if (!HeapTupleIsValid(tuple) || tuple->t_data == NULL)
685  return NULL;
686 
687  newTuple = (HeapTuple) palloc(HEAPTUPLESIZE + tuple->t_len);
688  newTuple->t_len = tuple->t_len;
689  newTuple->t_self = tuple->t_self;
690  newTuple->t_tableOid = tuple->t_tableOid;
691  newTuple->t_data = (HeapTupleHeader) ((char *) newTuple + HEAPTUPLESIZE);
692  memcpy((char *) newTuple->t_data, (char *) tuple->t_data, tuple->t_len);
693  return newTuple;
694 }
695 
696 /* ----------------
697  * heap_copytuple_with_tuple
698  *
699  * copy a tuple into a caller-supplied HeapTuple management struct
700  *
701  * Note that after calling this function, the "dest" HeapTuple will not be
702  * allocated as a single palloc() block (unlike with heap_copytuple()).
703  * ----------------
704  */
705 void
707 {
708  if (!HeapTupleIsValid(src) || src->t_data == NULL)
709  {
710  dest->t_data = NULL;
711  return;
712  }
713 
714  dest->t_len = src->t_len;
715  dest->t_self = src->t_self;
716  dest->t_tableOid = src->t_tableOid;
717  dest->t_data = (HeapTupleHeader) palloc(src->t_len);
718  memcpy((char *) dest->t_data, (char *) src->t_data, src->t_len);
719 }
720 
721 /*
722  * Expand a tuple which has fewer attributes than required. For each attribute
723  * not present in the sourceTuple, if there is a missing value that will be
724  * used. Otherwise the attribute will be set to NULL.
725  *
726  * The source tuple must have fewer attributes than the required number.
727  *
728  * Only one of targetHeapTuple and targetMinimalTuple may be supplied. The
729  * other argument must be NULL.
730  */
731 static void
732 expand_tuple(HeapTuple *targetHeapTuple,
733  MinimalTuple *targetMinimalTuple,
734  HeapTuple sourceTuple,
735  TupleDesc tupleDesc)
736 {
737  AttrMissing *attrmiss = NULL;
738  int attnum;
739  int firstmissingnum;
740  bool hasNulls = HeapTupleHasNulls(sourceTuple);
741  HeapTupleHeader targetTHeader;
742  HeapTupleHeader sourceTHeader = sourceTuple->t_data;
743  int sourceNatts = HeapTupleHeaderGetNatts(sourceTHeader);
744  int natts = tupleDesc->natts;
745  int sourceNullLen;
746  int targetNullLen;
747  Size sourceDataLen = sourceTuple->t_len - sourceTHeader->t_hoff;
748  Size targetDataLen;
749  Size len;
750  int hoff;
751  bits8 *nullBits = NULL;
752  int bitMask = 0;
753  char *targetData;
754  uint16 *infoMask;
755 
756  Assert((targetHeapTuple && !targetMinimalTuple)
757  || (!targetHeapTuple && targetMinimalTuple));
758 
759  Assert(sourceNatts < natts);
760 
761  sourceNullLen = (hasNulls ? BITMAPLEN(sourceNatts) : 0);
762 
763  targetDataLen = sourceDataLen;
764 
765  if (tupleDesc->constr &&
766  tupleDesc->constr->missing)
767  {
768  /*
769  * If there are missing values we want to put them into the tuple.
770  * Before that we have to compute the extra length for the values
771  * array and the variable length data.
772  */
773  attrmiss = tupleDesc->constr->missing;
774 
775  /*
776  * Find the first item in attrmiss for which we don't have a value in
777  * the source. We can ignore all the missing entries before that.
778  */
779  for (firstmissingnum = sourceNatts;
780  firstmissingnum < natts;
781  firstmissingnum++)
782  {
783  if (attrmiss[firstmissingnum].am_present)
784  break;
785  else
786  hasNulls = true;
787  }
788 
789  /*
790  * Now walk the missing attributes. If there is a missing value make
791  * space for it. Otherwise, it's going to be NULL.
792  */
793  for (attnum = firstmissingnum;
794  attnum < natts;
795  attnum++)
796  {
797  if (attrmiss[attnum].am_present)
798  {
799  Form_pg_attribute att = TupleDescAttr(tupleDesc, attnum);
800 
801  targetDataLen = att_align_datum(targetDataLen,
802  att->attalign,
803  att->attlen,
804  attrmiss[attnum].am_value);
805 
806  targetDataLen = att_addlength_pointer(targetDataLen,
807  att->attlen,
808  attrmiss[attnum].am_value);
809  }
810  else
811  {
812  /* no missing value, so it must be null */
813  hasNulls = true;
814  }
815  }
816  } /* end if have missing values */
817  else
818  {
819  /*
820  * If there are no missing values at all then NULLS must be allowed,
821  * since some of the attributes are known to be absent.
822  */
823  hasNulls = true;
824  }
825 
826  len = 0;
827 
828  if (hasNulls)
829  {
830  targetNullLen = BITMAPLEN(natts);
831  len += targetNullLen;
832  }
833  else
834  targetNullLen = 0;
835 
836  /*
837  * Allocate and zero the space needed. Note that the tuple body and
838  * HeapTupleData management structure are allocated in one chunk.
839  */
840  if (targetHeapTuple)
841  {
842  len += offsetof(HeapTupleHeaderData, t_bits);
843  hoff = len = MAXALIGN(len); /* align user data safely */
844  len += targetDataLen;
845 
846  *targetHeapTuple = (HeapTuple) palloc0(HEAPTUPLESIZE + len);
847  (*targetHeapTuple)->t_data
848  = targetTHeader
849  = (HeapTupleHeader) ((char *) *targetHeapTuple + HEAPTUPLESIZE);
850  (*targetHeapTuple)->t_len = len;
851  (*targetHeapTuple)->t_tableOid = sourceTuple->t_tableOid;
852  (*targetHeapTuple)->t_self = sourceTuple->t_self;
853 
854  targetTHeader->t_infomask = sourceTHeader->t_infomask;
855  targetTHeader->t_hoff = hoff;
856  HeapTupleHeaderSetNatts(targetTHeader, natts);
857  HeapTupleHeaderSetDatumLength(targetTHeader, len);
858  HeapTupleHeaderSetTypeId(targetTHeader, tupleDesc->tdtypeid);
859  HeapTupleHeaderSetTypMod(targetTHeader, tupleDesc->tdtypmod);
860  /* We also make sure that t_ctid is invalid unless explicitly set */
861  ItemPointerSetInvalid(&(targetTHeader->t_ctid));
862  if (targetNullLen > 0)
863  nullBits = (bits8 *) ((char *) (*targetHeapTuple)->t_data
864  + offsetof(HeapTupleHeaderData, t_bits));
865  targetData = (char *) (*targetHeapTuple)->t_data + hoff;
866  infoMask = &(targetTHeader->t_infomask);
867  }
868  else
869  {
871  hoff = len = MAXALIGN(len); /* align user data safely */
872  len += targetDataLen;
873 
874  *targetMinimalTuple = (MinimalTuple) palloc0(len);
875  (*targetMinimalTuple)->t_len = len;
876  (*targetMinimalTuple)->t_hoff = hoff + MINIMAL_TUPLE_OFFSET;
877  (*targetMinimalTuple)->t_infomask = sourceTHeader->t_infomask;
878  /* Same macro works for MinimalTuples */
879  HeapTupleHeaderSetNatts(*targetMinimalTuple, natts);
880  if (targetNullLen > 0)
881  nullBits = (bits8 *) ((char *) *targetMinimalTuple
882  + offsetof(MinimalTupleData, t_bits));
883  targetData = (char *) *targetMinimalTuple + hoff;
884  infoMask = &((*targetMinimalTuple)->t_infomask);
885  }
886 
887  if (targetNullLen > 0)
888  {
889  if (sourceNullLen > 0)
890  {
891  /* if bitmap pre-existed copy in - all is set */
892  memcpy(nullBits,
893  ((char *) sourceTHeader)
894  + offsetof(HeapTupleHeaderData, t_bits),
895  sourceNullLen);
896  nullBits += sourceNullLen - 1;
897  }
898  else
899  {
900  sourceNullLen = BITMAPLEN(sourceNatts);
901  /* Set NOT NULL for all existing attributes */
902  memset(nullBits, 0xff, sourceNullLen);
903 
904  nullBits += sourceNullLen - 1;
905 
906  if (sourceNatts & 0x07)
907  {
908  /* build the mask (inverted!) */
909  bitMask = 0xff << (sourceNatts & 0x07);
910  /* Voila */
911  *nullBits = ~bitMask;
912  }
913  }
914 
915  bitMask = (1 << ((sourceNatts - 1) & 0x07));
916  } /* End if have null bitmap */
917 
918  memcpy(targetData,
919  ((char *) sourceTuple->t_data) + sourceTHeader->t_hoff,
920  sourceDataLen);
921 
922  targetData += sourceDataLen;
923 
924  /* Now fill in the missing values */
925  for (attnum = sourceNatts; attnum < natts; attnum++)
926  {
927 
928  Form_pg_attribute attr = TupleDescAttr(tupleDesc, attnum);
929 
930  if (attrmiss && attrmiss[attnum].am_present)
931  {
932  fill_val(attr,
933  nullBits ? &nullBits : NULL,
934  &bitMask,
935  &targetData,
936  infoMask,
937  attrmiss[attnum].am_value,
938  false);
939  }
940  else
941  {
942  fill_val(attr,
943  &nullBits,
944  &bitMask,
945  &targetData,
946  infoMask,
947  (Datum) 0,
948  true);
949  }
950  } /* end loop over missing attributes */
951 }
952 
953 /*
954  * Fill in the missing values for a minimal HeapTuple
955  */
957 minimal_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc)
958 {
959  MinimalTuple minimalTuple;
960 
961  expand_tuple(NULL, &minimalTuple, sourceTuple, tupleDesc);
962  return minimalTuple;
963 }
964 
965 /*
966  * Fill in the missing values for an ordinary HeapTuple
967  */
968 HeapTuple
969 heap_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc)
970 {
971  HeapTuple heapTuple;
972 
973  expand_tuple(&heapTuple, NULL, sourceTuple, tupleDesc);
974  return heapTuple;
975 }
976 
977 /* ----------------
978  * heap_copy_tuple_as_datum
979  *
980  * copy a tuple as a composite-type Datum
981  * ----------------
982  */
983 Datum
985 {
986  HeapTupleHeader td;
987 
988  /*
989  * If the tuple contains any external TOAST pointers, we have to inline
990  * those fields to meet the conventions for composite-type Datums.
991  */
992  if (HeapTupleHasExternal(tuple))
993  return toast_flatten_tuple_to_datum(tuple->t_data,
994  tuple->t_len,
995  tupleDesc);
996 
997  /*
998  * Fast path for easy case: just make a palloc'd copy and insert the
999  * correct composite-Datum header fields (since those may not be set if
1000  * the given tuple came from disk, rather than from heap_form_tuple).
1001  */
1002  td = (HeapTupleHeader) palloc(tuple->t_len);
1003  memcpy((char *) td, (char *) tuple->t_data, tuple->t_len);
1004 
1006  HeapTupleHeaderSetTypeId(td, tupleDesc->tdtypeid);
1007  HeapTupleHeaderSetTypMod(td, tupleDesc->tdtypmod);
1008 
1009  return PointerGetDatum(td);
1010 }
1011 
1012 /*
1013  * heap_form_tuple
1014  * construct a tuple from the given values[] and isnull[] arrays,
1015  * which are of the length indicated by tupleDescriptor->natts
1016  *
1017  * The result is allocated in the current memory context.
1018  */
1019 HeapTuple
1020 heap_form_tuple(TupleDesc tupleDescriptor,
1021  Datum *values,
1022  bool *isnull)
1023 {
1024  HeapTuple tuple; /* return tuple */
1025  HeapTupleHeader td; /* tuple data */
1026  Size len,
1027  data_len;
1028  int hoff;
1029  bool hasnull = false;
1030  int numberOfAttributes = tupleDescriptor->natts;
1031  int i;
1032 
1033  if (numberOfAttributes > MaxTupleAttributeNumber)
1034  ereport(ERROR,
1035  (errcode(ERRCODE_TOO_MANY_COLUMNS),
1036  errmsg("number of columns (%d) exceeds limit (%d)",
1037  numberOfAttributes, MaxTupleAttributeNumber)));
1038 
1039  /*
1040  * Check for nulls
1041  */
1042  for (i = 0; i < numberOfAttributes; i++)
1043  {
1044  if (isnull[i])
1045  {
1046  hasnull = true;
1047  break;
1048  }
1049  }
1050 
1051  /*
1052  * Determine total space needed
1053  */
1054  len = offsetof(HeapTupleHeaderData, t_bits);
1055 
1056  if (hasnull)
1057  len += BITMAPLEN(numberOfAttributes);
1058 
1059  hoff = len = MAXALIGN(len); /* align user data safely */
1060 
1061  data_len = heap_compute_data_size(tupleDescriptor, values, isnull);
1062 
1063  len += data_len;
1064 
1065  /*
1066  * Allocate and zero the space needed. Note that the tuple body and
1067  * HeapTupleData management structure are allocated in one chunk.
1068  */
1069  tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + len);
1070  tuple->t_data = td = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE);
1071 
1072  /*
1073  * And fill in the information. Note we fill the Datum fields even though
1074  * this tuple may never become a Datum. This lets HeapTupleHeaderGetDatum
1075  * identify the tuple type if needed.
1076  */
1077  tuple->t_len = len;
1078  ItemPointerSetInvalid(&(tuple->t_self));
1079  tuple->t_tableOid = InvalidOid;
1080 
1082  HeapTupleHeaderSetTypeId(td, tupleDescriptor->tdtypeid);
1083  HeapTupleHeaderSetTypMod(td, tupleDescriptor->tdtypmod);
1084  /* We also make sure that t_ctid is invalid unless explicitly set */
1085  ItemPointerSetInvalid(&(td->t_ctid));
1086 
1087  HeapTupleHeaderSetNatts(td, numberOfAttributes);
1088  td->t_hoff = hoff;
1089 
1090  heap_fill_tuple(tupleDescriptor,
1091  values,
1092  isnull,
1093  (char *) td + hoff,
1094  data_len,
1095  &td->t_infomask,
1096  (hasnull ? td->t_bits : NULL));
1097 
1098  return tuple;
1099 }
1100 
1101 /*
1102  * heap_modify_tuple
1103  * form a new tuple from an old tuple and a set of replacement values.
1104  *
1105  * The replValues, replIsnull, and doReplace arrays must be of the length
1106  * indicated by tupleDesc->natts. The new tuple is constructed using the data
1107  * from replValues/replIsnull at columns where doReplace is true, and using
1108  * the data from the old tuple at columns where doReplace is false.
1109  *
1110  * The result is allocated in the current memory context.
1111  */
1112 HeapTuple
1114  TupleDesc tupleDesc,
1115  Datum *replValues,
1116  bool *replIsnull,
1117  bool *doReplace)
1118 {
1119  int numberOfAttributes = tupleDesc->natts;
1120  int attoff;
1121  Datum *values;
1122  bool *isnull;
1123  HeapTuple newTuple;
1124 
1125  /*
1126  * allocate and fill values and isnull arrays from either the tuple or the
1127  * repl information, as appropriate.
1128  *
1129  * NOTE: it's debatable whether to use heap_deform_tuple() here or just
1130  * heap_getattr() only the non-replaced columns. The latter could win if
1131  * there are many replaced columns and few non-replaced ones. However,
1132  * heap_deform_tuple costs only O(N) while the heap_getattr way would cost
1133  * O(N^2) if there are many non-replaced columns, so it seems better to
1134  * err on the side of linear cost.
1135  */
1136  values = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
1137  isnull = (bool *) palloc(numberOfAttributes * sizeof(bool));
1138 
1139  heap_deform_tuple(tuple, tupleDesc, values, isnull);
1140 
1141  for (attoff = 0; attoff < numberOfAttributes; attoff++)
1142  {
1143  if (doReplace[attoff])
1144  {
1145  values[attoff] = replValues[attoff];
1146  isnull[attoff] = replIsnull[attoff];
1147  }
1148  }
1149 
1150  /*
1151  * create a new tuple from the values and isnull arrays
1152  */
1153  newTuple = heap_form_tuple(tupleDesc, values, isnull);
1154 
1155  pfree(values);
1156  pfree(isnull);
1157 
1158  /*
1159  * copy the identification info of the old tuple: t_ctid, t_self
1160  */
1161  newTuple->t_data->t_ctid = tuple->t_data->t_ctid;
1162  newTuple->t_self = tuple->t_self;
1163  newTuple->t_tableOid = tuple->t_tableOid;
1164 
1165  return newTuple;
1166 }
1167 
1168 /*
1169  * heap_modify_tuple_by_cols
1170  * form a new tuple from an old tuple and a set of replacement values.
1171  *
1172  * This is like heap_modify_tuple, except that instead of specifying which
1173  * column(s) to replace by a boolean map, an array of target column numbers
1174  * is used. This is often more convenient when a fixed number of columns
1175  * are to be replaced. The replCols, replValues, and replIsnull arrays must
1176  * be of length nCols. Target column numbers are indexed from 1.
1177  *
1178  * The result is allocated in the current memory context.
1179  */
1180 HeapTuple
1182  TupleDesc tupleDesc,
1183  int nCols,
1184  int *replCols,
1185  Datum *replValues,
1186  bool *replIsnull)
1187 {
1188  int numberOfAttributes = tupleDesc->natts;
1189  Datum *values;
1190  bool *isnull;
1191  HeapTuple newTuple;
1192  int i;
1193 
1194  /*
1195  * allocate and fill values and isnull arrays from the tuple, then replace
1196  * selected columns from the input arrays.
1197  */
1198  values = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
1199  isnull = (bool *) palloc(numberOfAttributes * sizeof(bool));
1200 
1201  heap_deform_tuple(tuple, tupleDesc, values, isnull);
1202 
1203  for (i = 0; i < nCols; i++)
1204  {
1205  int attnum = replCols[i];
1206 
1207  if (attnum <= 0 || attnum > numberOfAttributes)
1208  elog(ERROR, "invalid column number %d", attnum);
1209  values[attnum - 1] = replValues[i];
1210  isnull[attnum - 1] = replIsnull[i];
1211  }
1212 
1213  /*
1214  * create a new tuple from the values and isnull arrays
1215  */
1216  newTuple = heap_form_tuple(tupleDesc, values, isnull);
1217 
1218  pfree(values);
1219  pfree(isnull);
1220 
1221  /*
1222  * copy the identification info of the old tuple: t_ctid, t_self
1223  */
1224  newTuple->t_data->t_ctid = tuple->t_data->t_ctid;
1225  newTuple->t_self = tuple->t_self;
1226  newTuple->t_tableOid = tuple->t_tableOid;
1227 
1228  return newTuple;
1229 }
1230 
1231 /*
1232  * heap_deform_tuple
1233  * Given a tuple, extract data into values/isnull arrays; this is
1234  * the inverse of heap_form_tuple.
1235  *
1236  * Storage for the values/isnull arrays is provided by the caller;
1237  * it should be sized according to tupleDesc->natts not
1238  * HeapTupleHeaderGetNatts(tuple->t_data).
1239  *
1240  * Note that for pass-by-reference datatypes, the pointer placed
1241  * in the Datum will point into the given tuple.
1242  *
1243  * When all or most of a tuple's fields need to be extracted,
1244  * this routine will be significantly quicker than a loop around
1245  * heap_getattr; the loop will become O(N^2) as soon as any
1246  * noncacheable attribute offsets are involved.
1247  */
1248 void
1250  Datum *values, bool *isnull)
1251 {
1252  HeapTupleHeader tup = tuple->t_data;
1253  bool hasnulls = HeapTupleHasNulls(tuple);
1254  int tdesc_natts = tupleDesc->natts;
1255  int natts; /* number of atts to extract */
1256  int attnum;
1257  char *tp; /* ptr to tuple data */
1258  uint32 off; /* offset in tuple data */
1259  bits8 *bp = tup->t_bits; /* ptr to null bitmap in tuple */
1260  bool slow = false; /* can we use/set attcacheoff? */
1261 
1262  natts = HeapTupleHeaderGetNatts(tup);
1263 
1264  /*
1265  * In inheritance situations, it is possible that the given tuple actually
1266  * has more fields than the caller is expecting. Don't run off the end of
1267  * the caller's arrays.
1268  */
1269  natts = Min(natts, tdesc_natts);
1270 
1271  tp = (char *) tup + tup->t_hoff;
1272 
1273  off = 0;
1274 
1275  for (attnum = 0; attnum < natts; attnum++)
1276  {
1277  Form_pg_attribute thisatt = TupleDescAttr(tupleDesc, attnum);
1278 
1279  if (hasnulls && att_isnull(attnum, bp))
1280  {
1281  values[attnum] = (Datum) 0;
1282  isnull[attnum] = true;
1283  slow = true; /* can't use attcacheoff anymore */
1284  continue;
1285  }
1286 
1287  isnull[attnum] = false;
1288 
1289  if (!slow && thisatt->attcacheoff >= 0)
1290  off = thisatt->attcacheoff;
1291  else if (thisatt->attlen == -1)
1292  {
1293  /*
1294  * We can only cache the offset for a varlena attribute if the
1295  * offset is already suitably aligned, so that there would be no
1296  * pad bytes in any case: then the offset will be valid for either
1297  * an aligned or unaligned value.
1298  */
1299  if (!slow &&
1300  off == att_align_nominal(off, thisatt->attalign))
1301  thisatt->attcacheoff = off;
1302  else
1303  {
1304  off = att_align_pointer(off, thisatt->attalign, -1,
1305  tp + off);
1306  slow = true;
1307  }
1308  }
1309  else
1310  {
1311  /* not varlena, so safe to use att_align_nominal */
1312  off = att_align_nominal(off, thisatt->attalign);
1313 
1314  if (!slow)
1315  thisatt->attcacheoff = off;
1316  }
1317 
1318  values[attnum] = fetchatt(thisatt, tp + off);
1319 
1320  off = att_addlength_pointer(off, thisatt->attlen, tp + off);
1321 
1322  if (thisatt->attlen <= 0)
1323  slow = true; /* can't use attcacheoff anymore */
1324  }
1325 
1326  /*
1327  * If tuple doesn't have all the atts indicated by tupleDesc, read the
1328  * rest as nulls or missing values as appropriate.
1329  */
1330  for (; attnum < tdesc_natts; attnum++)
1331  values[attnum] = getmissingattr(tupleDesc, attnum + 1, &isnull[attnum]);
1332 }
1333 
1334 /*
1335  * heap_freetuple
1336  */
1337 void
1339 {
1340  pfree(htup);
1341 }
1342 
1343 
1344 /*
1345  * heap_form_minimal_tuple
1346  * construct a MinimalTuple from the given values[] and isnull[] arrays,
1347  * which are of the length indicated by tupleDescriptor->natts
1348  *
1349  * This is exactly like heap_form_tuple() except that the result is a
1350  * "minimal" tuple lacking a HeapTupleData header as well as room for system
1351  * columns.
1352  *
1353  * The result is allocated in the current memory context.
1354  */
1357  Datum *values,
1358  bool *isnull)
1359 {
1360  MinimalTuple tuple; /* return tuple */
1361  Size len,
1362  data_len;
1363  int hoff;
1364  bool hasnull = false;
1365  int numberOfAttributes = tupleDescriptor->natts;
1366  int i;
1367 
1368  if (numberOfAttributes > MaxTupleAttributeNumber)
1369  ereport(ERROR,
1370  (errcode(ERRCODE_TOO_MANY_COLUMNS),
1371  errmsg("number of columns (%d) exceeds limit (%d)",
1372  numberOfAttributes, MaxTupleAttributeNumber)));
1373 
1374  /*
1375  * Check for nulls
1376  */
1377  for (i = 0; i < numberOfAttributes; i++)
1378  {
1379  if (isnull[i])
1380  {
1381  hasnull = true;
1382  break;
1383  }
1384  }
1385 
1386  /*
1387  * Determine total space needed
1388  */
1390 
1391  if (hasnull)
1392  len += BITMAPLEN(numberOfAttributes);
1393 
1394  hoff = len = MAXALIGN(len); /* align user data safely */
1395 
1396  data_len = heap_compute_data_size(tupleDescriptor, values, isnull);
1397 
1398  len += data_len;
1399 
1400  /*
1401  * Allocate and zero the space needed.
1402  */
1403  tuple = (MinimalTuple) palloc0(len);
1404 
1405  /*
1406  * And fill in the information.
1407  */
1408  tuple->t_len = len;
1409  HeapTupleHeaderSetNatts(tuple, numberOfAttributes);
1410  tuple->t_hoff = hoff + MINIMAL_TUPLE_OFFSET;
1411 
1412  heap_fill_tuple(tupleDescriptor,
1413  values,
1414  isnull,
1415  (char *) tuple + hoff,
1416  data_len,
1417  &tuple->t_infomask,
1418  (hasnull ? tuple->t_bits : NULL));
1419 
1420  return tuple;
1421 }
1422 
1423 /*
1424  * heap_free_minimal_tuple
1425  */
1426 void
1428 {
1429  pfree(mtup);
1430 }
1431 
1432 /*
1433  * heap_copy_minimal_tuple
1434  * copy a MinimalTuple
1435  *
1436  * The result is allocated in the current memory context.
1437  */
1440 {
1441  MinimalTuple result;
1442 
1443  result = (MinimalTuple) palloc(mtup->t_len);
1444  memcpy(result, mtup, mtup->t_len);
1445  return result;
1446 }
1447 
1448 /*
1449  * heap_tuple_from_minimal_tuple
1450  * create a HeapTuple by copying from a MinimalTuple;
1451  * system columns are filled with zeroes
1452  *
1453  * The result is allocated in the current memory context.
1454  * The HeapTuple struct, tuple header, and tuple data are all allocated
1455  * as a single palloc() block.
1456  */
1457 HeapTuple
1459 {
1460  HeapTuple result;
1462 
1463  result = (HeapTuple) palloc(HEAPTUPLESIZE + len);
1464  result->t_len = len;
1465  ItemPointerSetInvalid(&(result->t_self));
1466  result->t_tableOid = InvalidOid;
1467  result->t_data = (HeapTupleHeader) ((char *) result + HEAPTUPLESIZE);
1468  memcpy((char *) result->t_data + MINIMAL_TUPLE_OFFSET, mtup, mtup->t_len);
1469  memset(result->t_data, 0, offsetof(HeapTupleHeaderData, t_infomask2));
1470  return result;
1471 }
1472 
1473 /*
1474  * minimal_tuple_from_heap_tuple
1475  * create a MinimalTuple by copying from a HeapTuple
1476  *
1477  * The result is allocated in the current memory context.
1478  */
1481 {
1482  MinimalTuple result;
1483  uint32 len;
1484 
1486  len = htup->t_len - MINIMAL_TUPLE_OFFSET;
1487  result = (MinimalTuple) palloc(len);
1488  memcpy(result, (char *) htup->t_data + MINIMAL_TUPLE_OFFSET, len);
1489  result->t_len = len;
1490  return result;
1491 }
1492 
1493 /*
1494  * This mainly exists so JIT can inline the definition, but it's also
1495  * sometimes useful in debugging sessions.
1496  */
1497 size_t
1498 varsize_any(void *p)
1499 {
1500  return VARSIZE_ANY(p);
1501 }
static Datum values[MAXATTR]
Definition: bootstrap.c:156
unsigned short uint16
Definition: c.h:489
unsigned int uint32
Definition: c.h:490
#define Min(x, y)
Definition: c.h:988
#define MAXALIGN(LEN)
Definition: c.h:795
char * Pointer
Definition: c.h:467
uint8 bits8
Definition: c.h:497
#define HIGHBIT
Definition: c.h:1144
size_t Size
Definition: c.h:589
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
ExpandedObjectHeader * DatumGetEOHP(Datum d)
Definition: expandeddatum.c:29
void EOH_flatten_into(ExpandedObjectHeader *eohptr, void *result, Size allocated_size)
Definition: expandeddatum.c:81
Size EOH_get_flat_size(ExpandedObjectHeader *eohptr)
Definition: expandeddatum.c:75
Datum toast_flatten_tuple_to_datum(HeapTupleHeader tup, uint32 tup_len, TupleDesc tupleDesc)
Definition: heaptoast.c:449
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
void heap_copytuple_with_tuple(HeapTuple src, HeapTuple dest)
Definition: heaptuple.c:706
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
size_t varsize_any(void *p)
Definition: heaptuple.c:1498
MinimalTuple minimal_tuple_from_heap_tuple(HeapTuple htup)
Definition: heaptuple.c:1480
Datum heap_getsysattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: heaptuple.c:627
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
MinimalTuple heap_form_minimal_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1356
#define VARLENA_ATT_IS_PACKABLE(att)
Definition: heaptuple.c:71
void heap_free_minimal_tuple(MinimalTuple mtup)
Definition: heaptuple.c:1427
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:359
Datum nocachegetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:423
Datum getmissingattr(TupleDesc tupleDesc, int attnum, bool *isnull)
Definition: heaptuple.c:84
HeapTuple heap_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc)
Definition: heaptuple.c:969
#define ATT_IS_PACKABLE(att)
Definition: heaptuple.c:68
void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)
Definition: heaptuple.c:1249
MinimalTuple heap_copy_minimal_tuple(MinimalTuple mtup)
Definition: heaptuple.c:1439
Size heap_compute_data_size(TupleDesc tupleDesc, Datum *values, bool *isnull)
Definition: heaptuple.c:119
Datum heap_copy_tuple_as_datum(HeapTuple tuple, TupleDesc tupleDesc)
Definition: heaptuple.c:984
void heap_fill_tuple(TupleDesc tupleDesc, Datum *values, bool *isnull, char *data, Size data_size, uint16 *infomask, bits8 *bit)
Definition: heaptuple.c:304
static void expand_tuple(HeapTuple *targetHeapTuple, MinimalTuple *targetMinimalTuple, HeapTuple sourceTuple, TupleDesc tupleDesc)
Definition: heaptuple.c:732
HeapTuple heap_tuple_from_minimal_tuple(MinimalTuple mtup)
Definition: heaptuple.c:1458
MinimalTuple minimal_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc)
Definition: heaptuple.c:957
static void fill_val(Form_pg_attribute att, bits8 **bit, int *bitmask, char **dataP, uint16 *infomask, Datum datum, bool isnull)
Definition: heaptuple.c:175
HeapTuple heap_modify_tuple_by_cols(HeapTuple tuple, TupleDesc tupleDesc, int nCols, int *replCols, Datum *replValues, bool *replIsnull)
Definition: heaptuple.c:1181
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
#define HEAPTUPLESIZE
Definition: htup.h:73
HeapTupleData * HeapTuple
Definition: htup.h:71
MinimalTupleData * MinimalTuple
Definition: htup.h:27
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define HEAP_HASVARWIDTH
Definition: htup_details.h:191
#define MINIMAL_TUPLE_OFFSET
Definition: htup_details.h:617
#define HeapTupleHeaderSetTypMod(tup, typmod)
Definition: htup_details.h:471
#define HeapTupleHeaderGetNatts(tup)
Definition: htup_details.h:529
#define HEAP_HASNULL
Definition: htup_details.h:190
#define SizeofMinimalTupleHeader
Definition: htup_details.h:647
#define HeapTupleHasVarWidth(tuple)
Definition: htup_details.h:665
#define BITMAPLEN(NATTS)
Definition: htup_details.h:545
#define HeapTupleHasExternal(tuple)
Definition: htup_details.h:671
#define MaxTupleAttributeNumber
Definition: htup_details.h:34
#define HeapTupleNoNulls(tuple)
Definition: htup_details.h:662
#define HEAP_HASEXTERNAL
Definition: htup_details.h:192
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:304
#define HeapTupleHeaderSetNatts(tup, natts)
Definition: htup_details.h:532
#define HeapTupleHeaderSetDatumLength(tup, len)
Definition: htup_details.h:453
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:371
#define HeapTupleHeaderGetRawCommandId(tup)
Definition: htup_details.h:387
#define HeapTupleHasNulls(tuple)
Definition: htup_details.h:659
#define HeapTupleHeaderSetTypeId(tup, typeid)
Definition: htup_details.h:461
long val
Definition: informix.c:664
int j
Definition: isn.c:74
int i
Definition: isn.c:73
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
static void ItemPointerSetInvalid(ItemPointerData *pointer)
Definition: itemptr.h:184
Assert(fmt[strlen(fmt) - 1] !='\n')
void pfree(void *pointer)
Definition: mcxt.c:1436
void * palloc0(Size size)
Definition: mcxt.c:1241
void * palloc(Size size)
Definition: mcxt.c:1210
int16 attnum
Definition: pg_attribute.h:83
int16 attlen
Definition: pg_attribute.h:68
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:207
const void size_t len
const void * data
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
static char * DatumGetCString(Datum X)
Definition: postgres.h:335
static Datum TransactionIdGetDatum(TransactionId X)
Definition: postgres.h:272
uintptr_t Datum
Definition: postgres.h:64
static Datum CommandIdGetDatum(CommandId X)
Definition: postgres.h:302
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312
#define InvalidOid
Definition: postgres_ext.h:36
ItemPointerData t_self
Definition: htup.h:65
uint32 t_len
Definition: htup.h:64
HeapTupleHeader t_data
Definition: htup.h:68
Oid t_tableOid
Definition: htup.h:66
ItemPointerData t_ctid
Definition: htup_details.h:161
bits8 t_bits[FLEXIBLE_ARRAY_MEMBER]
Definition: htup_details.h:178
bits8 t_bits[FLEXIBLE_ARRAY_MEMBER]
Definition: htup_details.h:640
struct AttrMissing * missing
Definition: tupdesc.h:41
TupleConstr * constr
Definition: tupdesc.h:85
int32 tdtypmod
Definition: tupdesc.h:83
Oid tdtypeid
Definition: tupdesc.h:82
#define MinTransactionIdAttributeNumber
Definition: sysattr.h:22
#define MaxCommandIdAttributeNumber
Definition: sysattr.h:25
#define MaxTransactionIdAttributeNumber
Definition: sysattr.h:24
#define TableOidAttributeNumber
Definition: sysattr.h:26
#define SelfItemPointerAttributeNumber
Definition: sysattr.h:21
#define MinCommandIdAttributeNumber
Definition: sysattr.h:23
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
#define att_align_pointer(cur_offset, attalign, attlen, attptr)
Definition: tupmacs.h:107
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:129
#define att_align_datum(cur_offset, attalign, attlen, attdatum)
Definition: tupmacs.h:86
static bool att_isnull(int ATT, const bits8 *BITS)
Definition: tupmacs.h:26
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:157
#define fetchatt(A, T)
Definition: tupmacs.h:46
#define att_addlength_datum(cur_offset, attlen, attdatum)
Definition: tupmacs.h:145
static void store_att_byval(void *T, Datum newdatum, int attlen)
Definition: tupmacs.h:183
#define VARSIZE_SHORT(PTR)
Definition: varatt.h:281
#define SET_VARSIZE_SHORT(PTR, len)
Definition: varatt.h:306
#define VARATT_CAN_MAKE_SHORT(PTR)
Definition: varatt.h:258
#define VARATT_IS_EXTERNAL_EXPANDED(PTR)
Definition: varatt.h:298
#define VARATT_IS_SHORT(PTR)
Definition: varatt.h:302
#define VARSIZE_ANY(PTR)
Definition: varatt.h:311
#define VARDATA(PTR)
Definition: varatt.h:278
#define VARSIZE_EXTERNAL(PTR)
Definition: varatt.h:285
#define VARSIZE(PTR)
Definition: varatt.h:279
#define VARATT_CONVERTED_SHORT_SIZE(PTR)
Definition: varatt.h:261
#define VARATT_IS_EXTERNAL(PTR)
Definition: varatt.h:289
Datum bit(PG_FUNCTION_ARGS)
Definition: varbit.c:391