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