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