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