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