PostgreSQL Source Code git master
Loading...
Searching...
No Matches
heaptuple.c File Reference
#include "postgres.h"
#include "access/heaptoast.h"
#include "access/sysattr.h"
#include "access/tupdesc_details.h"
#include "common/hashfn.h"
#include "utils/datum.h"
#include "utils/expandeddatum.h"
#include "utils/hsearch.h"
#include "utils/memutils.h"
Include dependency graph for heaptuple.c:

Go to the source code of this file.

Data Structures

struct  missing_cache_key
 

Macros

#define ATT_IS_PACKABLE(att)    ((att)->attlen == -1 && (att)->attstorage != TYPSTORAGE_PLAIN)
 
#define VARLENA_ATT_IS_PACKABLE(att)    ((att)->attstorage != TYPSTORAGE_PLAIN)
 
#define COMPACT_ATTR_IS_PACKABLE(att)    ((att)->attlen == -1 && (att)->attispackable)
 

Functions

static uint32 missing_hash (const void *key, Size keysize)
 
static int missing_match (const void *key1, const void *key2, Size keysize)
 
static void init_missing_cache (void)
 
Datum getmissingattr (TupleDesc tupleDesc, int attnum, bool *isnull)
 
Size heap_compute_data_size (TupleDesc tupleDesc, const Datum *values, const bool *isnull)
 
static void fill_val (CompactAttribute *att, bits8 **bit, int *bitmask, char **dataP, uint16 *infomask, Datum datum, bool isnull)
 
void heap_fill_tuple (TupleDesc tupleDesc, const Datum *values, const bool *isnull, char *data, Size data_size, uint16 *infomask, bits8 *bit)
 
bool heap_attisnull (HeapTuple tup, int attnum, TupleDesc tupleDesc)
 
Datum nocachegetattr (HeapTuple tup, int attnum, TupleDesc tupleDesc)
 
Datum heap_getsysattr (HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
 
HeapTuple heap_copytuple (HeapTuple tuple)
 
void heap_copytuple_with_tuple (HeapTuple src, HeapTuple dest)
 
static void expand_tuple (HeapTuple *targetHeapTuple, MinimalTuple *targetMinimalTuple, HeapTuple sourceTuple, TupleDesc tupleDesc)
 
MinimalTuple minimal_expand_tuple (HeapTuple sourceTuple, TupleDesc tupleDesc)
 
HeapTuple heap_expand_tuple (HeapTuple sourceTuple, TupleDesc tupleDesc)
 
Datum heap_copy_tuple_as_datum (HeapTuple tuple, TupleDesc tupleDesc)
 
HeapTuple heap_form_tuple (TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
 
HeapTuple heap_modify_tuple (HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
 
HeapTuple heap_modify_tuple_by_cols (HeapTuple tuple, TupleDesc tupleDesc, int nCols, const int *replCols, const Datum *replValues, const bool *replIsnull)
 
void heap_deform_tuple (HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)
 
void heap_freetuple (HeapTuple htup)
 
MinimalTuple heap_form_minimal_tuple (TupleDesc tupleDescriptor, const Datum *values, const bool *isnull, Size extra)
 
void heap_free_minimal_tuple (MinimalTuple mtup)
 
MinimalTuple heap_copy_minimal_tuple (MinimalTuple mtup, Size extra)
 
HeapTuple heap_tuple_from_minimal_tuple (MinimalTuple mtup)
 
MinimalTuple minimal_tuple_from_heap_tuple (HeapTuple htup, Size extra)
 
size_t varsize_any (void *p)
 

Variables

static HTABmissing_cache = NULL
 

Macro Definition Documentation

◆ ATT_IS_PACKABLE

#define ATT_IS_PACKABLE (   att)     ((att)->attlen == -1 && (att)->attstorage != TYPSTORAGE_PLAIN)

Definition at line 80 of file heaptuple.c.

96{
97 int len;
100
101static HTAB *missing_cache = NULL;
102
103static uint32
104missing_hash(const void *key, Size keysize)
105{
106 const missing_cache_key *entry = key;
107
108 return hash_bytes((const unsigned char *) DatumGetPointer(entry->value), entry->len);
109}
110
111static int
112missing_match(const void *key1, const void *key2, Size keysize)
113{
114 const missing_cache_key *entry1 = key1;
116
117 if (entry1->len != entry2->len)
118 return entry1->len > entry2->len ? 1 : -1;
119
120 return memcmp(DatumGetPointer(entry1->value),
121 DatumGetPointer(entry2->value),
122 entry1->len);
123}
124
125static void
127{
129
131 hash_ctl.entrysize = sizeof(missing_cache_key);
133 hash_ctl.hash = missing_hash;
134 hash_ctl.match = missing_match;
136 hash_create("Missing Values Cache",
137 32,
138 &hash_ctl,
140}
141
142/* ----------------------------------------------------------------
143 * misc support routines
144 * ----------------------------------------------------------------
145 */
146
147/*
148 * Return the missing value of an attribute, or NULL if there isn't one.
149 */
150Datum
152 int attnum, bool *isnull)
153{
155
157 Assert(attnum > 0);
158
160
161 if (att->atthasmissing)
162 {
164
165 Assert(tupleDesc->constr);
166 Assert(tupleDesc->constr->missing);
167
168 attrmiss = tupleDesc->constr->missing + (attnum - 1);
169
170 if (attrmiss->am_present)
171 {
173 missing_cache_key *entry;
174 bool found;
176
177 *isnull = false;
178
179 /* no need to cache by-value attributes */
180 if (att->attbyval)
181 return attrmiss->am_value;
182
183 /* set up cache if required */
184 if (missing_cache == NULL)
186
187 /* check if there's a cache entry */
188 Assert(att->attlen > 0 || att->attlen == -1);
189 if (att->attlen > 0)
190 key.len = att->attlen;
191 else
192 key.len = VARSIZE_ANY(DatumGetPointer(attrmiss->am_value));
193 key.value = attrmiss->am_value;
194
195 entry = hash_search(missing_cache, &key, HASH_ENTER, &found);
196
197 if (!found)
198 {
199 /* cache miss, so we need a non-transient copy of the datum */
201 entry->value =
202 datumCopy(attrmiss->am_value, false, att->attlen);
204 }
205
206 return entry->value;
207 }
208 }
209
210 *isnull = true;
211 return PointerGetDatum(NULL);
212}
213
214/*
215 * heap_compute_data_size
216 * Determine size of the data area of a tuple to be constructed
217 */
218Size
220 const Datum *values,
221 const bool *isnull)
222{
223 Size data_length = 0;
224 int i;
225 int numberOfAttributes = tupleDesc->natts;
226
227 for (i = 0; i < numberOfAttributes; i++)
228 {
229 Datum val;
231
232 if (isnull[i])
233 continue;
234
235 val = values[i];
237
240 {
241 /*
242 * we're anticipating converting to a short varlena header, so
243 * adjust length and don't count any alignment
244 */
246 }
247 else if (atti->attlen == -1 &&
249 {
250 /*
251 * we want to flatten the expanded value so that the constructed
252 * tuple doesn't depend on it
253 */
254 data_length = att_nominal_alignby(data_length, atti->attalignby);
255 data_length += EOH_get_flat_size(DatumGetEOHP(val));
256 }
257 else
258 {
259 data_length = att_datum_alignby(data_length, atti->attalignby,
260 atti->attlen, val);
261 data_length = att_addlength_datum(data_length, atti->attlen,
262 val);
263 }
264 }
265
266 return data_length;
267}
268
269/*
270 * Per-attribute helper for heap_fill_tuple and other routines building tuples.
271 *
272 * Fill in either a data value or a bit in the null bitmask
273 */
274static inline void
276 bits8 **bit,
277 int *bitmask,
278 char **dataP,
280 Datum datum,
281 bool isnull)
282{
283 Size data_length;
284 char *data = *dataP;
285
286 /*
287 * If we're building a null bitmap, set the appropriate bit for the
288 * current column value here.
289 */
290 if (bit != NULL)
291 {
292 if (*bitmask != HIGHBIT)
293 *bitmask <<= 1;
294 else
295 {
296 *bit += 1;
297 **bit = 0x0;
298 *bitmask = 1;
299 }
300
301 if (isnull)
302 {
304 return;
305 }
306
307 **bit |= *bitmask;
308 }
309
310 /*
311 * XXX we use the att_nominal_alignby macro on the pointer value itself,
312 * not on an offset. This is a bit of a hack.
313 */
314 if (att->attbyval)
315 {
316 /* pass-by-value */
317 data = (char *) att_nominal_alignby(data, att->attalignby);
318 store_att_byval(data, datum, att->attlen);
319 data_length = att->attlen;
320 }
321 else if (att->attlen == -1)
322 {
323 /* varlena */
324 Pointer val = DatumGetPointer(datum);
325
328 {
330 {
331 /*
332 * we want to flatten the expanded value so that the
333 * constructed tuple doesn't depend on it
334 */
336
337 data = (char *) att_nominal_alignby(data, att->attalignby);
338 data_length = EOH_get_flat_size(eoh);
339 EOH_flatten_into(eoh, data, data_length);
340 }
341 else
342 {
344 /* no alignment, since it's short by definition */
345 data_length = VARSIZE_EXTERNAL(val);
346 memcpy(data, val, data_length);
347 }
348 }
349 else if (VARATT_IS_SHORT(val))
350 {
351 /* no alignment for short varlenas */
352 data_length = VARSIZE_SHORT(val);
353 memcpy(data, val, data_length);
354 }
355 else if (att->attispackable && VARATT_CAN_MAKE_SHORT(val))
356 {
357 /* convert to short varlena -- no alignment */
358 data_length = VARATT_CONVERTED_SHORT_SIZE(val);
359 SET_VARSIZE_SHORT(data, data_length);
360 memcpy(data + 1, VARDATA(val), data_length - 1);
361 }
362 else
363 {
364 /* full 4-byte header varlena */
365 data = (char *) att_nominal_alignby(data, att->attalignby);
366 data_length = VARSIZE(val);
367 memcpy(data, val, data_length);
368 }
369 }
370 else if (att->attlen == -2)
371 {
372 /* cstring ... never needs alignment */
374 Assert(att->attalignby == sizeof(char));
375 data_length = strlen(DatumGetCString(datum)) + 1;
376 memcpy(data, DatumGetPointer(datum), data_length);
377 }
378 else
379 {
380 /* fixed-length pass-by-reference */
381 data = (char *) att_nominal_alignby(data, att->attalignby);
382 Assert(att->attlen > 0);
383 data_length = att->attlen;
384 memcpy(data, DatumGetPointer(datum), data_length);
385 }
386
387 data += data_length;
388 *dataP = data;
389}
390
391/*
392 * heap_fill_tuple
393 * Load data portion of a tuple from values/isnull arrays
394 *
395 * We also fill the null bitmap (if any) and set the infomask bits
396 * that reflect the tuple's data contents.
397 *
398 * NOTE: it is now REQUIRED that the caller have pre-zeroed the data area.
399 */
400void
402 const Datum *values, const bool *isnull,
403 char *data, Size data_size,
405{
406 bits8 *bitP;
407 int bitmask;
408 int i;
409 int numberOfAttributes = tupleDesc->natts;
410
411#ifdef USE_ASSERT_CHECKING
412 char *start = data;
413#endif
414
415 if (bit != NULL)
416 {
417 bitP = &bit[-1];
418 bitmask = HIGHBIT;
419 }
420 else
421 {
422 /* just to keep compiler quiet */
423 bitP = NULL;
424 bitmask = 0;
425 }
426
428
429 for (i = 0; i < numberOfAttributes; i++)
430 {
432
433 fill_val(attr,
434 bitP ? &bitP : NULL,
435 &bitmask,
436 &data,
437 infomask,
439 isnull ? isnull[i] : true);
440 }
441
442 Assert((data - start) == data_size);
443}
444
445
446/* ----------------------------------------------------------------
447 * heap tuple interface
448 * ----------------------------------------------------------------
449 */
450
451/* ----------------
452 * heap_attisnull - returns true iff tuple attribute is not present
453 * ----------------
454 */
455bool
457{
458 /*
459 * We allow a NULL tupledesc for relations not expected to have missing
460 * values, such as catalog relations and indexes.
461 */
463 if (attnum > (int) HeapTupleHeaderGetNatts(tup->t_data))
464 {
465 if (tupleDesc &&
466 TupleDescCompactAttr(tupleDesc, attnum - 1)->atthasmissing)
467 return false;
468 else
469 return true;
470 }
471
472 if (attnum > 0)
473 {
475 return false;
476 return att_isnull(attnum - 1, tup->t_data->t_bits);
477 }
478
479 switch (attnum)
480 {
487 /* these are never null */
488 break;
489
490 default:
491 elog(ERROR, "invalid attnum: %d", attnum);
492 }
493
494 return false;
495}
496
497/* ----------------
498 * nocachegetattr
499 *
500 * This only gets called from fastgetattr(), in cases where we
501 * can't use the attcacheoff and the value is not null.
502 *
503 * NOTE: if you need to change this code, see also heap_deform_tuple.
504 * Also see nocache_index_getattr, which is the same code for index
505 * tuples.
506 * ----------------
507 */
508Datum
510 int attnum,
512{
514 HeapTupleHeader td = tup->t_data;
515 char *tp; /* ptr to data part of tuple */
516 bits8 *bp = td->t_bits; /* ptr to null bitmap in tuple */
517 int off; /* current offset within data */
518 int startAttr;
519 int firstNullAttr;
520 int i;
522
523 /* Did someone forget to call TupleDescFinalize()? */
524 Assert(tupleDesc->firstNonCachedOffsetAttr >= 0);
525
526 attnum--;
527
528 /*
529 * To minimize the number of attributes we need to look at, start walking
530 * the tuple at the attribute with the highest attcacheoff prior to attnum
531 * or the first NULL attribute prior to attnum, whichever comes first.
532 */
533 if (hasnulls)
535 else
537
538 if (tupleDesc->firstNonCachedOffsetAttr > 0 && firstNullAttr > 0)
539 {
540 /*
541 * Try to start with the highest attribute with an attcacheoff that's
542 * prior to the one we're looking for, or with the attribute prior to
543 * the first NULL attribute, if there is one.
544 */
545 startAttr = Min(tupleDesc->firstNonCachedOffsetAttr - 1, firstNullAttr - 1);
547 }
548 else
549 {
550 /* Otherwise, start at the beginning... */
551 startAttr = 0;
552 off = 0;
553 }
554
555 tp = (char *) td + td->t_hoff;
556
557 /*
558 * Calculate 'off' up to the first NULL attr. We use two cheaper loops
559 * when the tuple has no variable-width columns. When variable-width
560 * columns exists, we use att_addlength_pointer() to move the offset
561 * beyond the current attribute.
562 */
564 {
565 for (i = startAttr; i < firstNullAttr; i++)
566 {
568
569 off = att_nominal_alignby(off, cattr->attalignby);
570 off += cattr->attlen;
571 }
572
573 for (; i < attnum; i++)
574 {
575 if (att_isnull(i, bp))
576 continue;
577
579
580 off = att_nominal_alignby(off, cattr->attalignby);
581 off += cattr->attlen;
582 }
583 }
584 else
585 {
586 for (i = startAttr; i < firstNullAttr; i++)
587 {
588 int attlen;
589
591 attlen = cattr->attlen;
592
593 /*
594 * cstrings don't exist in heap tuples. Use pg_assume to instruct
595 * the compiler not to emit the cstring-related code in
596 * att_addlength_pointer().
597 */
598 pg_assume(attlen > 0 || attlen == -1);
599
600 off = att_pointer_alignby(off,
601 cattr->attalignby,
602 attlen,
603 tp + off);
604 off = att_addlength_pointer(off, attlen, tp + off);
605 }
606
607 for (; i < attnum; i++)
608 {
609 int attlen;
610
611 if (att_isnull(i, bp))
612 continue;
613
615 attlen = cattr->attlen;
616
617 /* As above, heaptuples have no cstrings */
618 pg_assume(attlen > 0 || attlen == -1);
619
620 off = att_pointer_alignby(off, cattr->attalignby, attlen,
621 tp + off);
622 off = att_addlength_pointer(off, attlen, tp + off);
623 }
624 }
625
627 off = att_pointer_alignby(off,
628 cattr->attalignby,
629 cattr->attlen,
630 tp + off);
631
632 return fetchatt(cattr, tp + off);
633}
634
635/* ----------------
636 * heap_getsysattr
637 *
638 * Fetch the value of a system attribute for a tuple.
639 *
640 * This is a support routine for heap_getattr(). The function has already
641 * determined that the attnum refers to a system attribute.
642 * ----------------
643 */
644Datum
646{
647 Datum result;
648
649 Assert(tup);
650
651 /* Currently, no sys attribute ever reads as NULL. */
652 *isnull = false;
653
654 switch (attnum)
655 {
657 /* pass-by-reference datatype */
658 result = PointerGetDatum(&(tup->t_self));
659 break;
662 break;
665 break;
668
669 /*
670 * cmin and cmax are now both aliases for the same field, which
671 * can in fact also be a combo command id. XXX perhaps we should
672 * return the "real" cmin or cmax if possible, that is if we are
673 * inside the originating transaction?
674 */
676 break;
678 result = ObjectIdGetDatum(tup->t_tableOid);
679 break;
680 default:
681 elog(ERROR, "invalid attnum: %d", attnum);
682 result = 0; /* keep compiler quiet */
683 break;
684 }
685 return result;
686}
687
688/* ----------------
689 * heap_copytuple
690 *
691 * returns a copy of an entire tuple
692 *
693 * The HeapTuple struct, tuple header, and tuple data are all allocated
694 * as a single palloc() block.
695 * ----------------
696 */
699{
701
702 if (!HeapTupleIsValid(tuple) || tuple->t_data == NULL)
703 return NULL;
704
706 newTuple->t_len = tuple->t_len;
707 newTuple->t_self = tuple->t_self;
708 newTuple->t_tableOid = tuple->t_tableOid;
709 newTuple->t_data = (HeapTupleHeader) ((char *) newTuple + HEAPTUPLESIZE);
710 memcpy(newTuple->t_data, tuple->t_data, tuple->t_len);
711 return newTuple;
712}
713
714/* ----------------
715 * heap_copytuple_with_tuple
716 *
717 * copy a tuple into a caller-supplied HeapTuple management struct
718 *
719 * Note that after calling this function, the "dest" HeapTuple will not be
720 * allocated as a single palloc() block (unlike with heap_copytuple()).
721 * ----------------
722 */
723void
725{
726 if (!HeapTupleIsValid(src) || src->t_data == NULL)
727 {
728 dest->t_data = NULL;
729 return;
730 }
731
732 dest->t_len = src->t_len;
733 dest->t_self = src->t_self;
734 dest->t_tableOid = src->t_tableOid;
735 dest->t_data = (HeapTupleHeader) palloc(src->t_len);
736 memcpy(dest->t_data, src->t_data, src->t_len);
737}
738
739/*
740 * Expand a tuple which has fewer attributes than required. For each attribute
741 * not present in the sourceTuple, if there is a missing value that will be
742 * used. Otherwise the attribute will be set to NULL.
743 *
744 * The source tuple must have fewer attributes than the required number.
745 *
746 * Only one of targetHeapTuple and targetMinimalTuple may be supplied. The
747 * other argument must be NULL.
748 */
749static void
754{
756 int attnum;
757 int firstmissingnum;
762 int natts = tupleDesc->natts;
763 int sourceNullLen;
764 int targetNullLen;
765 Size sourceDataLen = sourceTuple->t_len - sourceTHeader->t_hoff;
767 Size len;
768 int hoff;
770 int bitMask = 0;
771 char *targetData;
773
776
777 Assert(sourceNatts < natts);
778
780
782
783 if (tupleDesc->constr &&
784 tupleDesc->constr->missing)
785 {
786 /*
787 * If there are missing values we want to put them into the tuple.
788 * Before that we have to compute the extra length for the values
789 * array and the variable length data.
790 */
791 attrmiss = tupleDesc->constr->missing;
792
793 /*
794 * Find the first item in attrmiss for which we don't have a value in
795 * the source. We can ignore all the missing entries before that.
796 */
798 firstmissingnum < natts;
800 {
801 if (attrmiss[firstmissingnum].am_present)
802 break;
803 else
804 hasNulls = true;
805 }
806
807 /*
808 * Now walk the missing attributes. If there is a missing value make
809 * space for it. Otherwise, it's going to be NULL.
810 */
811 for (attnum = firstmissingnum;
812 attnum < natts;
813 attnum++)
814 {
815 if (attrmiss[attnum].am_present)
816 {
818
820 att->attalignby,
821 att->attlen,
822 attrmiss[attnum].am_value);
823
825 att->attlen,
826 attrmiss[attnum].am_value);
827 }
828 else
829 {
830 /* no missing value, so it must be null */
831 hasNulls = true;
832 }
833 }
834 } /* end if have missing values */
835 else
836 {
837 /*
838 * If there are no missing values at all then NULLS must be allowed,
839 * since some of the attributes are known to be absent.
840 */
841 hasNulls = true;
842 }
843
844 len = 0;
845
846 if (hasNulls)
847 {
848 targetNullLen = BITMAPLEN(natts);
850 }
851 else
852 targetNullLen = 0;
853
854 /*
855 * Allocate and zero the space needed. Note that the tuple body and
856 * HeapTupleData management structure are allocated in one chunk.
857 */
858 if (targetHeapTuple)
859 {
860 len += offsetof(HeapTupleHeaderData, t_bits);
861 hoff = len = MAXALIGN(len); /* align user data safely */
863
865 (*targetHeapTuple)->t_data
868 (*targetHeapTuple)->t_len = len;
869 (*targetHeapTuple)->t_tableOid = sourceTuple->t_tableOid;
870 (*targetHeapTuple)->t_self = sourceTuple->t_self;
871
872 targetTHeader->t_infomask = sourceTHeader->t_infomask;
873 targetTHeader->t_hoff = hoff;
878 /* We also make sure that t_ctid is invalid unless explicitly set */
880 if (targetNullLen > 0)
881 nullBits = (bits8 *) ((char *) (*targetHeapTuple)->t_data
882 + offsetof(HeapTupleHeaderData, t_bits));
883 targetData = (char *) (*targetHeapTuple)->t_data + hoff;
884 infoMask = &(targetTHeader->t_infomask);
885 }
886 else
887 {
889 hoff = len = MAXALIGN(len); /* align user data safely */
891
893 (*targetMinimalTuple)->t_len = len;
894 (*targetMinimalTuple)->t_hoff = hoff + MINIMAL_TUPLE_OFFSET;
895 (*targetMinimalTuple)->t_infomask = sourceTHeader->t_infomask;
896 /* Same macro works for MinimalTuples */
898 if (targetNullLen > 0)
899 nullBits = (bits8 *) ((char *) *targetMinimalTuple
900 + offsetof(MinimalTupleData, t_bits));
901 targetData = (char *) *targetMinimalTuple + hoff;
902 infoMask = &((*targetMinimalTuple)->t_infomask);
903 }
904
905 if (targetNullLen > 0)
906 {
907 if (sourceNullLen > 0)
908 {
909 /* if bitmap pre-existed copy in - all is set */
911 ((char *) sourceTHeader)
912 + offsetof(HeapTupleHeaderData, t_bits),
914 nullBits += sourceNullLen - 1;
915 }
916 else
917 {
919 /* Set NOT NULL for all existing attributes */
921
922 nullBits += sourceNullLen - 1;
923
924 if (sourceNatts & 0x07)
925 {
926 /* build the mask (inverted!) */
927 bitMask = 0xff << (sourceNatts & 0x07);
928 /* Voila */
930 }
931 }
932
933 bitMask = (1 << ((sourceNatts - 1) & 0x07));
934 } /* End if have null bitmap */
935
937 ((char *) sourceTuple->t_data) + sourceTHeader->t_hoff,
939
941
942 /* Now fill in the missing values */
943 for (attnum = sourceNatts; attnum < natts; attnum++)
944 {
946
947 if (attrmiss && attrmiss[attnum].am_present)
948 {
949 fill_val(attr,
951 &bitMask,
952 &targetData,
953 infoMask,
954 attrmiss[attnum].am_value,
955 false);
956 }
957 else
958 {
959 fill_val(attr,
960 &nullBits,
961 &bitMask,
962 &targetData,
963 infoMask,
964 (Datum) 0,
965 true);
966 }
967 } /* end loop over missing attributes */
968}
969
970/*
971 * Fill in the missing values for a minimal HeapTuple
972 */
975{
977
979 return minimalTuple;
980}
981
982/*
983 * Fill in the missing values for an ordinary HeapTuple
984 */
987{
989
991 return heapTuple;
992}
993
994/* ----------------
995 * heap_copy_tuple_as_datum
996 *
997 * copy a tuple as a composite-type Datum
998 * ----------------
999 */
1000Datum
1002{
1003 HeapTupleHeader td;
1004
1005 /*
1006 * If the tuple contains any external TOAST pointers, we have to inline
1007 * those fields to meet the conventions for composite-type Datums.
1008 */
1009 if (HeapTupleHasExternal(tuple))
1011 tuple->t_len,
1012 tupleDesc);
1013
1014 /*
1015 * Fast path for easy case: just make a palloc'd copy and insert the
1016 * correct composite-Datum header fields (since those may not be set if
1017 * the given tuple came from disk, rather than from heap_form_tuple).
1018 */
1019 td = (HeapTupleHeader) palloc(tuple->t_len);
1020 memcpy(td, tuple->t_data, tuple->t_len);
1021
1023 HeapTupleHeaderSetTypeId(td, tupleDesc->tdtypeid);
1024 HeapTupleHeaderSetTypMod(td, tupleDesc->tdtypmod);
1025
1026 return PointerGetDatum(td);
1027}
1028
1029/*
1030 * heap_form_tuple
1031 * construct a tuple from the given values[] and isnull[] arrays,
1032 * which are of the length indicated by tupleDescriptor->natts
1033 *
1034 * The result is allocated in the current memory context.
1035 */
1038 const Datum *values,
1039 const bool *isnull)
1040{
1041 HeapTuple tuple; /* return tuple */
1042 HeapTupleHeader td; /* tuple data */
1043 Size len,
1044 data_len;
1045 int hoff;
1046 bool hasnull = false;
1048 int i;
1049
1051 ereport(ERROR,
1053 errmsg("number of columns (%d) exceeds limit (%d)",
1055
1056 /*
1057 * Check for nulls
1058 */
1059 for (i = 0; i < numberOfAttributes; i++)
1060 {
1061 if (isnull[i])
1062 {
1063 hasnull = true;
1064 break;
1065 }
1066 }
1067
1068 /*
1069 * Determine total space needed
1070 */
1071 len = offsetof(HeapTupleHeaderData, t_bits);
1072
1073 if (hasnull)
1075
1076 hoff = len = MAXALIGN(len); /* align user data safely */
1077
1078 data_len = heap_compute_data_size(tupleDescriptor, values, isnull);
1079
1080 len += data_len;
1081
1082 /*
1083 * Allocate and zero the space needed. Note that the tuple body and
1084 * HeapTupleData management structure are allocated in one chunk.
1085 */
1086 tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + len);
1087 tuple->t_data = td = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE);
1088
1089 /*
1090 * And fill in the information. Note we fill the Datum fields even though
1091 * this tuple may never become a Datum. This lets HeapTupleHeaderGetDatum
1092 * identify the tuple type if needed.
1093 */
1094 tuple->t_len = len;
1095 ItemPointerSetInvalid(&(tuple->t_self));
1096 tuple->t_tableOid = InvalidOid;
1097
1101 /* We also make sure that t_ctid is invalid unless explicitly set */
1103
1105 td->t_hoff = hoff;
1106
1108 values,
1109 isnull,
1110 (char *) td + hoff,
1111 data_len,
1112 &td->t_infomask,
1113 (hasnull ? td->t_bits : NULL));
1114
1115 return tuple;
1116}
1117
1118/*
1119 * heap_modify_tuple
1120 * form a new tuple from an old tuple and a set of replacement values.
1121 *
1122 * The replValues, replIsnull, and doReplace arrays must be of the length
1123 * indicated by tupleDesc->natts. The new tuple is constructed using the data
1124 * from replValues/replIsnull at columns where doReplace is true, and using
1125 * the data from the old tuple at columns where doReplace is false.
1126 *
1127 * The result is allocated in the current memory context.
1128 */
1132 const Datum *replValues,
1133 const bool *replIsnull,
1134 const bool *doReplace)
1135{
1136 int numberOfAttributes = tupleDesc->natts;
1137 int attoff;
1138 Datum *values;
1139 bool *isnull;
1141
1142 /*
1143 * allocate and fill values and isnull arrays from either the tuple or the
1144 * repl information, as appropriate.
1145 *
1146 * NOTE: it's debatable whether to use heap_deform_tuple() here or just
1147 * heap_getattr() only the non-replaced columns. The latter could win if
1148 * there are many replaced columns and few non-replaced ones. However,
1149 * heap_deform_tuple costs only O(N) while the heap_getattr way would cost
1150 * O(N^2) if there are many non-replaced columns, so it seems better to
1151 * err on the side of linear cost.
1152 */
1154 isnull = palloc_array(bool, numberOfAttributes);
1155
1156 heap_deform_tuple(tuple, tupleDesc, values, isnull);
1157
1158 for (attoff = 0; attoff < numberOfAttributes; attoff++)
1159 {
1160 if (doReplace[attoff])
1161 {
1163 isnull[attoff] = replIsnull[attoff];
1164 }
1165 }
1166
1167 /*
1168 * create a new tuple from the values and isnull arrays
1169 */
1171
1172 pfree(values);
1173 pfree(isnull);
1174
1175 /*
1176 * copy the identification info of the old tuple: t_ctid, t_self
1177 */
1178 newTuple->t_data->t_ctid = tuple->t_data->t_ctid;
1179 newTuple->t_self = tuple->t_self;
1180 newTuple->t_tableOid = tuple->t_tableOid;
1181
1182 return newTuple;
1183}
1184
1185/*
1186 * heap_modify_tuple_by_cols
1187 * form a new tuple from an old tuple and a set of replacement values.
1188 *
1189 * This is like heap_modify_tuple, except that instead of specifying which
1190 * column(s) to replace by a boolean map, an array of target column numbers
1191 * is used. This is often more convenient when a fixed number of columns
1192 * are to be replaced. The replCols, replValues, and replIsnull arrays must
1193 * be of length nCols. Target column numbers are indexed from 1.
1194 *
1195 * The result is allocated in the current memory context.
1196 */
1200 int nCols,
1201 const int *replCols,
1202 const Datum *replValues,
1203 const bool *replIsnull)
1204{
1205 int numberOfAttributes = tupleDesc->natts;
1206 Datum *values;
1207 bool *isnull;
1209 int i;
1210
1211 /*
1212 * allocate and fill values and isnull arrays from the tuple, then replace
1213 * selected columns from the input arrays.
1214 */
1216 isnull = palloc_array(bool, numberOfAttributes);
1217
1218 heap_deform_tuple(tuple, tupleDesc, values, isnull);
1219
1220 for (i = 0; i < nCols; i++)
1221 {
1222 int attnum = replCols[i];
1223
1225 elog(ERROR, "invalid column number %d", attnum);
1226 values[attnum - 1] = replValues[i];
1227 isnull[attnum - 1] = replIsnull[i];
1228 }
1229
1230 /*
1231 * create a new tuple from the values and isnull arrays
1232 */
1234
1235 pfree(values);
1236 pfree(isnull);
1237
1238 /*
1239 * copy the identification info of the old tuple: t_ctid, t_self
1240 */
1241 newTuple->t_data->t_ctid = tuple->t_data->t_ctid;
1242 newTuple->t_self = tuple->t_self;
1243 newTuple->t_tableOid = tuple->t_tableOid;
1244
1245 return newTuple;
1246}
1247
1248/*
1249 * heap_deform_tuple
1250 * Given a tuple, extract data into values/isnull arrays; this is
1251 * the inverse of heap_form_tuple.
1252 *
1253 * Storage for the values/isnull arrays is provided by the caller;
1254 * it should be sized according to tupleDesc->natts not
1255 * HeapTupleHeaderGetNatts(tuple->t_data).
1256 *
1257 * Note that for pass-by-reference datatypes, the pointer placed
1258 * in the Datum will point into the given tuple.
1259 *
1260 * When all or most of a tuple's fields need to be extracted,
1261 * this routine will be significantly quicker than a loop around
1262 * heap_getattr; the loop will become O(N^2) as soon as any
1263 * noncacheable attribute offsets are involved.
1264 */
1265void
1267 Datum *values, bool *isnull)
1268{
1269 HeapTupleHeader tup = tuple->t_data;
1271 bool hasnulls = HeapTupleHasNulls(tuple);
1272 int tdesc_natts = tupleDesc->natts;
1273 int natts; /* number of atts to extract */
1274 int attnum;
1275 char *tp; /* ptr to tuple data */
1276 uint32 off; /* offset in tuple data */
1277 bits8 *bp = tup->t_bits; /* ptr to null bitmap in tuple */
1279 int firstNullAttr;
1280
1282
1283 /* Did someone forget to call TupleDescFinalize()? */
1284 Assert(tupleDesc->firstNonCachedOffsetAttr >= 0);
1285
1286 /*
1287 * In inheritance situations, it is possible that the given tuple actually
1288 * has more fields than the caller is expecting. Don't run off the end of
1289 * the caller's arrays.
1290 */
1291 natts = Min(natts, tdesc_natts);
1292 firstNonCacheOffsetAttr = Min(tupleDesc->firstNonCachedOffsetAttr, natts);
1293
1294 if (hasnulls)
1295 {
1297
1298 /*
1299 * XXX: it'd be nice to use populate_isnull_array() here, but that
1300 * requires that the isnull array's size is rounded up to the next
1301 * multiple of 8. Doing that would require adjusting many locations
1302 * that allocate the array.
1303 */
1305 }
1306 else
1307 firstNullAttr = natts;
1308
1309 tp = (char *) tup + tup->t_hoff;
1310 attnum = 0;
1311
1313 {
1314#ifdef USE_ASSERT_CHECKING
1315 /* In Assert enabled builds, verify attcacheoff is correct */
1316 int offcheck = 0;
1317#endif
1318 do
1319 {
1320 isnull[attnum] = false;
1322 off = cattr->attcacheoff;
1323
1324#ifdef USE_ASSERT_CHECKING
1326 Assert(offcheck == cattr->attcacheoff);
1327 offcheck += cattr->attlen;
1328#endif
1329
1330 values[attnum] = fetch_att_noerr(tp + off,
1331 cattr->attbyval,
1332 cattr->attlen);
1333 } while (++attnum < firstNonCacheOffsetAttr);
1334 off += cattr->attlen;
1335 }
1336 else
1337 off = 0;
1338
1339 for (; attnum < firstNullAttr; attnum++)
1340 {
1341 isnull[attnum] = false;
1344 &off,
1345 cattr->attbyval,
1346 cattr->attlen,
1347 cattr->attalignby);
1348 }
1349
1350 for (; attnum < natts; attnum++)
1351 {
1353
1354 if (att_isnull(attnum, bp))
1355 {
1356 values[attnum] = (Datum) 0;
1357 isnull[attnum] = true;
1358 continue;
1359 }
1360
1361 isnull[attnum] = false;
1363
1364 /* align 'off', fetch the attr's value, and increment off beyond it */
1366 &off,
1367 cattr->attbyval,
1368 cattr->attlen,
1369 cattr->attalignby);
1370 }
1371
1372 /*
1373 * If tuple doesn't have all the atts indicated by tupleDesc, read the
1374 * rest as nulls or missing values as appropriate.
1375 */
1376 for (; attnum < tdesc_natts; attnum++)
1378}
1379
1380/*
1381 * heap_freetuple
1382 */
1383void
1385{
1386 pfree(htup);
1387}
1388
1389
1390/*
1391 * heap_form_minimal_tuple
1392 * construct a MinimalTuple from the given values[] and isnull[] arrays,
1393 * which are of the length indicated by tupleDescriptor->natts
1394 *
1395 * This is exactly like heap_form_tuple() except that the result is a
1396 * "minimal" tuple lacking a HeapTupleData header as well as room for system
1397 * columns.
1398 *
1399 * The result is allocated in the current memory context.
1400 */
1403 const Datum *values,
1404 const bool *isnull,
1405 Size extra)
1406{
1407 MinimalTuple tuple; /* return tuple */
1408 char *mem;
1409 Size len,
1410 data_len;
1411 int hoff;
1412 bool hasnull = false;
1414 int i;
1415
1416 Assert(extra == MAXALIGN(extra));
1417
1419 ereport(ERROR,
1421 errmsg("number of columns (%d) exceeds limit (%d)",
1423
1424 /*
1425 * Check for nulls
1426 */
1427 for (i = 0; i < numberOfAttributes; i++)
1428 {
1429 if (isnull[i])
1430 {
1431 hasnull = true;
1432 break;
1433 }
1434 }
1435
1436 /*
1437 * Determine total space needed
1438 */
1440
1441 if (hasnull)
1443
1444 hoff = len = MAXALIGN(len); /* align user data safely */
1445
1446 data_len = heap_compute_data_size(tupleDescriptor, values, isnull);
1447
1448 len += data_len;
1449
1450 /*
1451 * Allocate and zero the space needed.
1452 */
1453 mem = palloc0(len + extra);
1454 tuple = (MinimalTuple) (mem + extra);
1455
1456 /*
1457 * And fill in the information.
1458 */
1459 tuple->t_len = len;
1461 tuple->t_hoff = hoff + MINIMAL_TUPLE_OFFSET;
1462
1464 values,
1465 isnull,
1466 (char *) tuple + hoff,
1467 data_len,
1468 &tuple->t_infomask,
1469 (hasnull ? tuple->t_bits : NULL));
1470
1471 return tuple;
1472}
1473
1474/*
1475 * heap_free_minimal_tuple
1476 */
1477void
1479{
1480 pfree(mtup);
1481}
1482
1483/*
1484 * heap_copy_minimal_tuple
1485 * copy a MinimalTuple
1486 *
1487 * The result is allocated in the current memory context.
1488 */
1491{
1492 MinimalTuple result;
1493 char *mem;
1494
1495 Assert(extra == MAXALIGN(extra));
1496 mem = palloc(mtup->t_len + extra);
1497 memset(mem, 0, extra);
1498 result = (MinimalTuple) (mem + extra);
1499 memcpy(result, mtup, mtup->t_len);
1500 return result;
1501}
1502
1503/*
1504 * heap_tuple_from_minimal_tuple
1505 * create a HeapTuple by copying from a MinimalTuple;
1506 * system columns are filled with zeroes
1507 *
1508 * The result is allocated in the current memory context.
1509 * The HeapTuple struct, tuple header, and tuple data are all allocated
1510 * as a single palloc() block.
1511 */
1514{
1515 HeapTuple result;
1517
1518 result = (HeapTuple) palloc(HEAPTUPLESIZE + len);
1519 result->t_len = len;
1520 ItemPointerSetInvalid(&(result->t_self));
1521 result->t_tableOid = InvalidOid;
1522 result->t_data = (HeapTupleHeader) ((char *) result + HEAPTUPLESIZE);
1523 memcpy((char *) result->t_data + MINIMAL_TUPLE_OFFSET, mtup, mtup->t_len);
1524 memset(result->t_data, 0, offsetof(HeapTupleHeaderData, t_infomask2));
1525 return result;
1526}
1527
1528/*
1529 * minimal_tuple_from_heap_tuple
1530 * create a MinimalTuple by copying from a HeapTuple
1531 *
1532 * The result is allocated in the current memory context.
1533 */
1536{
1537 MinimalTuple result;
1538 char *mem;
1539 uint32 len;
1540
1541 Assert(extra == MAXALIGN(extra));
1543 len = htup->t_len - MINIMAL_TUPLE_OFFSET;
1544 mem = palloc(len + extra);
1545 memset(mem, 0, extra);
1546 result = (MinimalTuple) (mem + extra);
1547 memcpy(result, (char *) htup->t_data + MINIMAL_TUPLE_OFFSET, len);
1548
1549 result->t_len = len;
1550 return result;
1551}
1552
1553/*
1554 * This mainly exists so JIT can inline the definition, but it's also
1555 * sometimes useful in debugging sessions.
1556 */
1557size_t
1558varsize_any(void *p)
1559{
1560 return VARSIZE_ANY(p);
1561}
static Datum values[MAXATTR]
Definition bootstrap.c:188
#define Min(x, y)
Definition c.h:1093
#define MAXALIGN(LEN)
Definition c.h:898
#define Assert(condition)
Definition c.h:945
uint8 bits8
Definition c.h:625
uint16_t uint16
Definition c.h:617
#define pg_assume(expr)
Definition c.h:417
uint32_t uint32
Definition c.h:618
void * Pointer
Definition c.h:609
#define HIGHBIT
Definition c.h:1245
size_t Size
Definition c.h:691
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition datum.c:132
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition dynahash.c:952
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
Definition dynahash.c:358
int errcode(int sqlerrcode)
Definition elog.c:874
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
#define ereport(elevel,...)
Definition elog.h:150
ExpandedObjectHeader * DatumGetEOHP(Datum d)
void EOH_flatten_into(ExpandedObjectHeader *eohptr, void *result, Size allocated_size)
Size EOH_get_flat_size(ExpandedObjectHeader *eohptr)
#define palloc_array(type, count)
Definition fe_memutils.h:76
uint32 hash_bytes(const unsigned char *k, int keylen)
Definition hashfn.c:146
return str start
Datum toast_flatten_tuple_to_datum(HeapTupleHeader tup, uint32 tup_len, TupleDesc tupleDesc)
Definition heaptoast.c:449
Size heap_compute_data_size(TupleDesc tupleDesc, const Datum *values, const bool *isnull)
Definition heaptuple.c:219
static uint32 missing_hash(const void *key, Size keysize)
Definition heaptuple.c:104
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
Definition heaptuple.c:1130
void heap_copytuple_with_tuple(HeapTuple src, HeapTuple dest)
Definition heaptuple.c:724
HeapTuple heap_copytuple(HeapTuple tuple)
Definition heaptuple.c:698
size_t varsize_any(void *p)
Definition heaptuple.c:1558
MinimalTuple heap_copy_minimal_tuple(MinimalTuple mtup, Size extra)
Definition heaptuple.c:1490
Datum heap_getsysattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition heaptuple.c:645
MinimalTuple heap_form_minimal_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull, Size extra)
Definition heaptuple.c:1402
HeapTuple heap_modify_tuple_by_cols(HeapTuple tuple, TupleDesc tupleDesc, int nCols, const int *replCols, const Datum *replValues, const bool *replIsnull)
Definition heaptuple.c:1198
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition heaptuple.c:1037
void heap_free_minimal_tuple(MinimalTuple mtup)
Definition heaptuple.c:1478
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition heaptuple.c:456
Datum nocachegetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition heaptuple.c:509
Datum getmissingattr(TupleDesc tupleDesc, int attnum, bool *isnull)
Definition heaptuple.c:151
MinimalTuple minimal_tuple_from_heap_tuple(HeapTuple htup, Size extra)
Definition heaptuple.c:1535
HeapTuple heap_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc)
Definition heaptuple.c:986
static void fill_val(CompactAttribute *att, bits8 **bit, int *bitmask, char **dataP, uint16 *infomask, Datum datum, bool isnull)
Definition heaptuple.c:275
void heap_fill_tuple(TupleDesc tupleDesc, const Datum *values, const bool *isnull, char *data, Size data_size, uint16 *infomask, bits8 *bit)
Definition heaptuple.c:401
#define COMPACT_ATTR_IS_PACKABLE(att)
Definition heaptuple.c:87
void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)
Definition heaptuple.c:1266
static void init_missing_cache(void)
Definition heaptuple.c:126
static int missing_match(const void *key1, const void *key2, Size keysize)
Definition heaptuple.c:112
Datum heap_copy_tuple_as_datum(HeapTuple tuple, TupleDesc tupleDesc)
Definition heaptuple.c:1001
static HTAB * missing_cache
Definition heaptuple.c:101
static void expand_tuple(HeapTuple *targetHeapTuple, MinimalTuple *targetMinimalTuple, HeapTuple sourceTuple, TupleDesc tupleDesc)
Definition heaptuple.c:750
HeapTuple heap_tuple_from_minimal_tuple(MinimalTuple mtup)
Definition heaptuple.c:1513
MinimalTuple minimal_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc)
Definition heaptuple.c:974
void heap_freetuple(HeapTuple htup)
Definition heaptuple.c:1384
@ HASH_ENTER
Definition hsearch.h:114
#define HASH_CONTEXT
Definition hsearch.h:102
#define HASH_ELEM
Definition hsearch.h:95
#define HASH_COMPARE
Definition hsearch.h:99
#define HASH_FUNCTION
Definition hsearch.h:98
#define HEAPTUPLESIZE
Definition htup.h:73
HeapTupleData * HeapTuple
Definition htup.h:71
MinimalTupleData * MinimalTuple
Definition htup.h:27
HeapTupleHeaderData * HeapTupleHeader
Definition htup.h:23
#define HeapTupleIsValid(tuple)
Definition htup.h:78
#define HEAP_HASVARWIDTH
#define MINIMAL_TUPLE_OFFSET
#define HeapTupleHeaderGetNatts(tup)
static void HeapTupleHeaderSetTypMod(HeapTupleHeaderData *tup, int32 typmod)
static bool HeapTupleHasNulls(const HeapTupleData *tuple)
#define HEAP_HASNULL
static int BITMAPLEN(int NATTS)
static bool HeapTupleHasExternal(const HeapTupleData *tuple)
#define SizeofMinimalTupleHeader
static void HeapTupleHeaderSetTypeId(HeapTupleHeaderData *tup, Oid datum_typeid)
static CommandId HeapTupleHeaderGetRawCommandId(const HeapTupleHeaderData *tup)
static TransactionId HeapTupleHeaderGetRawXmax(const HeapTupleHeaderData *tup)
#define MaxTupleAttributeNumber
static bool HeapTupleNoNulls(const HeapTupleData *tuple)
#define HEAP_HASEXTERNAL
static void HeapTupleHeaderSetDatumLength(HeapTupleHeaderData *tup, uint32 len)
static TransactionId HeapTupleHeaderGetRawXmin(const HeapTupleHeaderData *tup)
#define HeapTupleHeaderSetNatts(tup, natts)
static bool HeapTupleHasVarWidth(const HeapTupleData *tuple)
#define false
long val
Definition informix.c:689
static struct @174 value
return true
Definition isn.c:130
int i
Definition isn.c:77
static void ItemPointerSetInvalid(ItemPointerData *pointer)
Definition itemptr.h:184
void pfree(void *pointer)
Definition mcxt.c:1616
void * palloc0(Size size)
Definition mcxt.c:1417
MemoryContext TopMemoryContext
Definition mcxt.c:166
void * palloc(Size size)
Definition mcxt.c:1387
static char * errmsg
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
int16 attnum
int16 attlen
const void size_t len
const void * data
static Datum PointerGetDatum(const void *X)
Definition postgres.h:342
static Datum TransactionIdGetDatum(TransactionId X)
Definition postgres.h:292
static Datum CommandIdGetDatum(CommandId X)
Definition postgres.h:322
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
static char * DatumGetCString(Datum X)
Definition postgres.h:355
uint64_t Datum
Definition postgres.h:70
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:332
#define InvalidOid
static int fb(int x)
int16 attcacheoff
Definition tupdesc.h:70
Size keysize
Definition hsearch.h:75
ItemPointerData t_self
Definition htup.h:65
uint32 t_len
Definition htup.h:64
HeapTupleHeader t_data
Definition htup.h:68
Oid t_tableOid
Definition htup.h:66
ItemPointerData t_ctid
bits8 t_bits[FLEXIBLE_ARRAY_MEMBER]
bits8 t_bits[FLEXIBLE_ARRAY_MEMBER]
#define MinTransactionIdAttributeNumber
Definition sysattr.h:22
#define MaxCommandIdAttributeNumber
Definition sysattr.h:25
#define MaxTransactionIdAttributeNumber
Definition sysattr.h:24
#define TableOidAttributeNumber
Definition sysattr.h:26
#define SelfItemPointerAttributeNumber
Definition sysattr.h:21
#define MinCommandIdAttributeNumber
Definition sysattr.h:23
static CompactAttribute * TupleDescCompactAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:193
#define att_nominal_alignby(cur_offset, attalignby)
Definition tupmacs.h:411
static int first_null_attr(const bits8 *bits, int natts)
Definition tupmacs.h:244
#define att_datum_alignby(cur_offset, attalignby, attlen, attdatum)
Definition tupmacs.h:352
static bool att_isnull(int ATT, const bits8 *BITS)
Definition tupmacs.h:28
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition tupmacs.h:431
static Datum align_fetch_then_add(const char *tupptr, uint32 *off, bool attbyval, int attlen, uint8 attalignby)
Definition tupmacs.h:172
#define att_pointer_alignby(cur_offset, attalignby, attlen, attptr)
Definition tupmacs.h:383
#define fetchatt(A, T)
Definition tupmacs.h:102
static Datum fetch_att_noerr(const void *T, bool attbyval, int attlen)
Definition tupmacs.h:137
#define att_addlength_datum(cur_offset, attlen, attdatum)
Definition tupmacs.h:419
static void store_att_byval(void *T, Datum newdatum, int attlen)
Definition tupmacs.h:457
static bool VARATT_IS_SHORT(const void *PTR)
Definition varatt.h:403
static Size VARSIZE_ANY(const void *PTR)
Definition varatt.h:460
static bool VARATT_CAN_MAKE_SHORT(const void *PTR)
Definition varatt.h:417
static bool VARATT_IS_EXTERNAL(const void *PTR)
Definition varatt.h:354
static Size VARSIZE(const void *PTR)
Definition varatt.h:298
static char * VARDATA(const void *PTR)
Definition varatt.h:305
static Size VARATT_CONVERTED_SHORT_SIZE(const void *PTR)
Definition varatt.h:425
static Size VARSIZE_EXTERNAL(const void *PTR)
Definition varatt.h:333
static bool VARATT_IS_EXTERNAL_EXPANDED(const void *PTR)
Definition varatt.h:389
static void SET_VARSIZE_SHORT(void *PTR, Size len)
Definition varatt.h:439
static Size VARSIZE_SHORT(const void *PTR)
Definition varatt.h:312
Datum bit(PG_FUNCTION_ARGS)
Definition varbit.c:391

◆ COMPACT_ATTR_IS_PACKABLE

#define COMPACT_ATTR_IS_PACKABLE (   att)     ((att)->attlen == -1 && (att)->attispackable)

Definition at line 87 of file heaptuple.c.

◆ VARLENA_ATT_IS_PACKABLE

#define VARLENA_ATT_IS_PACKABLE (   att)     ((att)->attstorage != TYPSTORAGE_PLAIN)

Definition at line 83 of file heaptuple.c.

Function Documentation

◆ expand_tuple()

static void expand_tuple ( HeapTuple targetHeapTuple,
MinimalTuple targetMinimalTuple,
HeapTuple  sourceTuple,
TupleDesc  tupleDesc 
)
static

Definition at line 750 of file heaptuple.c.

754{
756 int attnum;
757 int firstmissingnum;
762 int natts = tupleDesc->natts;
763 int sourceNullLen;
764 int targetNullLen;
765 Size sourceDataLen = sourceTuple->t_len - sourceTHeader->t_hoff;
767 Size len;
768 int hoff;
770 int bitMask = 0;
771 char *targetData;
773
776
777 Assert(sourceNatts < natts);
778
780
782
783 if (tupleDesc->constr &&
784 tupleDesc->constr->missing)
785 {
786 /*
787 * If there are missing values we want to put them into the tuple.
788 * Before that we have to compute the extra length for the values
789 * array and the variable length data.
790 */
791 attrmiss = tupleDesc->constr->missing;
792
793 /*
794 * Find the first item in attrmiss for which we don't have a value in
795 * the source. We can ignore all the missing entries before that.
796 */
798 firstmissingnum < natts;
800 {
801 if (attrmiss[firstmissingnum].am_present)
802 break;
803 else
804 hasNulls = true;
805 }
806
807 /*
808 * Now walk the missing attributes. If there is a missing value make
809 * space for it. Otherwise, it's going to be NULL.
810 */
811 for (attnum = firstmissingnum;
812 attnum < natts;
813 attnum++)
814 {
815 if (attrmiss[attnum].am_present)
816 {
818
820 att->attalignby,
821 att->attlen,
822 attrmiss[attnum].am_value);
823
825 att->attlen,
826 attrmiss[attnum].am_value);
827 }
828 else
829 {
830 /* no missing value, so it must be null */
831 hasNulls = true;
832 }
833 }
834 } /* end if have missing values */
835 else
836 {
837 /*
838 * If there are no missing values at all then NULLS must be allowed,
839 * since some of the attributes are known to be absent.
840 */
841 hasNulls = true;
842 }
843
844 len = 0;
845
846 if (hasNulls)
847 {
848 targetNullLen = BITMAPLEN(natts);
850 }
851 else
852 targetNullLen = 0;
853
854 /*
855 * Allocate and zero the space needed. Note that the tuple body and
856 * HeapTupleData management structure are allocated in one chunk.
857 */
858 if (targetHeapTuple)
859 {
860 len += offsetof(HeapTupleHeaderData, t_bits);
861 hoff = len = MAXALIGN(len); /* align user data safely */
863
865 (*targetHeapTuple)->t_data
868 (*targetHeapTuple)->t_len = len;
869 (*targetHeapTuple)->t_tableOid = sourceTuple->t_tableOid;
870 (*targetHeapTuple)->t_self = sourceTuple->t_self;
871
872 targetTHeader->t_infomask = sourceTHeader->t_infomask;
873 targetTHeader->t_hoff = hoff;
878 /* We also make sure that t_ctid is invalid unless explicitly set */
880 if (targetNullLen > 0)
881 nullBits = (bits8 *) ((char *) (*targetHeapTuple)->t_data
882 + offsetof(HeapTupleHeaderData, t_bits));
883 targetData = (char *) (*targetHeapTuple)->t_data + hoff;
884 infoMask = &(targetTHeader->t_infomask);
885 }
886 else
887 {
889 hoff = len = MAXALIGN(len); /* align user data safely */
891
893 (*targetMinimalTuple)->t_len = len;
894 (*targetMinimalTuple)->t_hoff = hoff + MINIMAL_TUPLE_OFFSET;
895 (*targetMinimalTuple)->t_infomask = sourceTHeader->t_infomask;
896 /* Same macro works for MinimalTuples */
898 if (targetNullLen > 0)
899 nullBits = (bits8 *) ((char *) *targetMinimalTuple
900 + offsetof(MinimalTupleData, t_bits));
901 targetData = (char *) *targetMinimalTuple + hoff;
902 infoMask = &((*targetMinimalTuple)->t_infomask);
903 }
904
905 if (targetNullLen > 0)
906 {
907 if (sourceNullLen > 0)
908 {
909 /* if bitmap pre-existed copy in - all is set */
911 ((char *) sourceTHeader)
912 + offsetof(HeapTupleHeaderData, t_bits),
914 nullBits += sourceNullLen - 1;
915 }
916 else
917 {
919 /* Set NOT NULL for all existing attributes */
921
922 nullBits += sourceNullLen - 1;
923
924 if (sourceNatts & 0x07)
925 {
926 /* build the mask (inverted!) */
927 bitMask = 0xff << (sourceNatts & 0x07);
928 /* Voila */
930 }
931 }
932
933 bitMask = (1 << ((sourceNatts - 1) & 0x07));
934 } /* End if have null bitmap */
935
937 ((char *) sourceTuple->t_data) + sourceTHeader->t_hoff,
939
941
942 /* Now fill in the missing values */
943 for (attnum = sourceNatts; attnum < natts; attnum++)
944 {
946
947 if (attrmiss && attrmiss[attnum].am_present)
948 {
949 fill_val(attr,
951 &bitMask,
952 &targetData,
953 infoMask,
954 attrmiss[attnum].am_value,
955 false);
956 }
957 else
958 {
959 fill_val(attr,
960 &nullBits,
961 &bitMask,
962 &targetData,
963 infoMask,
964 (Datum) 0,
965 true);
966 }
967 } /* end loop over missing attributes */
968}

References Assert, att_addlength_datum, att_datum_alignby, attnum, BITMAPLEN(), fb(), fill_val(), HeapTupleHasNulls(), HeapTupleHeaderGetNatts, HeapTupleHeaderSetDatumLength(), HeapTupleHeaderSetNatts, HeapTupleHeaderSetTypeId(), HeapTupleHeaderSetTypMod(), HEAPTUPLESIZE, ItemPointerSetInvalid(), len, MAXALIGN, MINIMAL_TUPLE_OFFSET, palloc0(), SizeofMinimalTupleHeader, and TupleDescCompactAttr().

Referenced by heap_expand_tuple(), and minimal_expand_tuple().

◆ fill_val()

static void fill_val ( CompactAttribute att,
bits8 **  bit,
int bitmask,
char **  dataP,
uint16 infomask,
Datum  datum,
bool  isnull 
)
inlinestatic

Definition at line 275 of file heaptuple.c.

282{
283 Size data_length;
284 char *data = *dataP;
285
286 /*
287 * If we're building a null bitmap, set the appropriate bit for the
288 * current column value here.
289 */
290 if (bit != NULL)
291 {
292 if (*bitmask != HIGHBIT)
293 *bitmask <<= 1;
294 else
295 {
296 *bit += 1;
297 **bit = 0x0;
298 *bitmask = 1;
299 }
300
301 if (isnull)
302 {
304 return;
305 }
306
307 **bit |= *bitmask;
308 }
309
310 /*
311 * XXX we use the att_nominal_alignby macro on the pointer value itself,
312 * not on an offset. This is a bit of a hack.
313 */
314 if (att->attbyval)
315 {
316 /* pass-by-value */
317 data = (char *) att_nominal_alignby(data, att->attalignby);
318 store_att_byval(data, datum, att->attlen);
319 data_length = att->attlen;
320 }
321 else if (att->attlen == -1)
322 {
323 /* varlena */
324 Pointer val = DatumGetPointer(datum);
325
328 {
330 {
331 /*
332 * we want to flatten the expanded value so that the
333 * constructed tuple doesn't depend on it
334 */
336
337 data = (char *) att_nominal_alignby(data, att->attalignby);
338 data_length = EOH_get_flat_size(eoh);
339 EOH_flatten_into(eoh, data, data_length);
340 }
341 else
342 {
344 /* no alignment, since it's short by definition */
345 data_length = VARSIZE_EXTERNAL(val);
346 memcpy(data, val, data_length);
347 }
348 }
349 else if (VARATT_IS_SHORT(val))
350 {
351 /* no alignment for short varlenas */
352 data_length = VARSIZE_SHORT(val);
353 memcpy(data, val, data_length);
354 }
355 else if (att->attispackable && VARATT_CAN_MAKE_SHORT(val))
356 {
357 /* convert to short varlena -- no alignment */
358 data_length = VARATT_CONVERTED_SHORT_SIZE(val);
359 SET_VARSIZE_SHORT(data, data_length);
360 memcpy(data + 1, VARDATA(val), data_length - 1);
361 }
362 else
363 {
364 /* full 4-byte header varlena */
365 data = (char *) att_nominal_alignby(data, att->attalignby);
366 data_length = VARSIZE(val);
367 memcpy(data, val, data_length);
368 }
369 }
370 else if (att->attlen == -2)
371 {
372 /* cstring ... never needs alignment */
374 Assert(att->attalignby == sizeof(char));
375 data_length = strlen(DatumGetCString(datum)) + 1;
376 memcpy(data, DatumGetPointer(datum), data_length);
377 }
378 else
379 {
380 /* fixed-length pass-by-reference */
381 data = (char *) att_nominal_alignby(data, att->attalignby);
382 Assert(att->attlen > 0);
383 data_length = att->attlen;
384 memcpy(data, DatumGetPointer(datum), data_length);
385 }
386
387 data += data_length;
388 *dataP = data;
389}

References Assert, att_nominal_alignby, bit(), data, DatumGetCString(), DatumGetEOHP(), DatumGetPointer(), EOH_flatten_into(), EOH_get_flat_size(), fb(), HEAP_HASEXTERNAL, HEAP_HASNULL, HEAP_HASVARWIDTH, HIGHBIT, SET_VARSIZE_SHORT(), store_att_byval(), val, VARATT_CAN_MAKE_SHORT(), VARATT_CONVERTED_SHORT_SIZE(), VARATT_IS_EXTERNAL(), VARATT_IS_EXTERNAL_EXPANDED(), VARATT_IS_SHORT(), VARDATA(), VARSIZE(), VARSIZE_EXTERNAL(), and VARSIZE_SHORT().

Referenced by expand_tuple(), and heap_fill_tuple().

◆ getmissingattr()

Datum getmissingattr ( TupleDesc  tupleDesc,
int  attnum,
bool isnull 
)

Definition at line 151 of file heaptuple.c.

153{
155
157 Assert(attnum > 0);
158
160
161 if (att->atthasmissing)
162 {
164
165 Assert(tupleDesc->constr);
166 Assert(tupleDesc->constr->missing);
167
168 attrmiss = tupleDesc->constr->missing + (attnum - 1);
169
170 if (attrmiss->am_present)
171 {
173 missing_cache_key *entry;
174 bool found;
176
177 *isnull = false;
178
179 /* no need to cache by-value attributes */
180 if (att->attbyval)
181 return attrmiss->am_value;
182
183 /* set up cache if required */
184 if (missing_cache == NULL)
186
187 /* check if there's a cache entry */
188 Assert(att->attlen > 0 || att->attlen == -1);
189 if (att->attlen > 0)
190 key.len = att->attlen;
191 else
192 key.len = VARSIZE_ANY(DatumGetPointer(attrmiss->am_value));
193 key.value = attrmiss->am_value;
194
195 entry = hash_search(missing_cache, &key, HASH_ENTER, &found);
196
197 if (!found)
198 {
199 /* cache miss, so we need a non-transient copy of the datum */
201 entry->value =
202 datumCopy(attrmiss->am_value, false, att->attlen);
204 }
205
206 return entry->value;
207 }
208 }
209
210 *isnull = true;
211 return PointerGetDatum(NULL);
212}

References Assert, attnum, datumCopy(), DatumGetPointer(), fb(), HASH_ENTER, hash_search(), init_missing_cache(), MemoryContextSwitchTo(), missing_cache, PointerGetDatum(), TopMemoryContext, TupleDescCompactAttr(), missing_cache_key::value, and VARSIZE_ANY().

Referenced by heap_deform_tuple(), and heap_getattr().

◆ heap_attisnull()

bool heap_attisnull ( HeapTuple  tup,
int  attnum,
TupleDesc  tupleDesc 
)

Definition at line 456 of file heaptuple.c.

457{
458 /*
459 * We allow a NULL tupledesc for relations not expected to have missing
460 * values, such as catalog relations and indexes.
461 */
463 if (attnum > (int) HeapTupleHeaderGetNatts(tup->t_data))
464 {
465 if (tupleDesc &&
466 TupleDescCompactAttr(tupleDesc, attnum - 1)->atthasmissing)
467 return false;
468 else
469 return true;
470 }
471
472 if (attnum > 0)
473 {
475 return false;
476 return att_isnull(attnum - 1, tup->t_data->t_bits);
477 }
478
479 switch (attnum)
480 {
487 /* these are never null */
488 break;
489
490 default:
491 elog(ERROR, "invalid attnum: %d", attnum);
492 }
493
494 return false;
495}

References Assert, att_isnull(), attnum, elog, ERROR, fb(), HeapTupleHeaderGetNatts, HeapTupleNoNulls(), MaxCommandIdAttributeNumber, MaxTransactionIdAttributeNumber, MinCommandIdAttributeNumber, MinTransactionIdAttributeNumber, SelfItemPointerAttributeNumber, TableOidAttributeNumber, and TupleDescCompactAttr().

Referenced by AlterPublicationOptions(), AlterPublicationSchemas(), build_function_result_tupdesc_t(), check_index_is_clusterable(), check_modified_virtual_generated(), CheckIndexCompatible(), ExecEvalRowNullInt(), ExecuteCallStmt(), fmgr_info_cxt_security(), fmgr_symbol(), get_func_result_name(), index_drop(), inline_function(), inline_function_in_from(), IsIndexUsableForReplicaIdentityFull(), pg_get_indexdef_worker(), pg_get_partkeydef_worker(), pg_get_statisticsobj_worker(), pg_get_statisticsobjdef_expressions(), RelationGetDummyIndexExpressions(), RelationGetIndexExpressions(), RelationGetIndexList(), RelationGetIndexPredicate(), statext_is_kind_built(), and transformFkeyCheckAttrs().

◆ heap_compute_data_size()

Size heap_compute_data_size ( TupleDesc  tupleDesc,
const Datum values,
const bool isnull 
)

Definition at line 219 of file heaptuple.c.

222{
223 Size data_length = 0;
224 int i;
225 int numberOfAttributes = tupleDesc->natts;
226
227 for (i = 0; i < numberOfAttributes; i++)
228 {
229 Datum val;
231
232 if (isnull[i])
233 continue;
234
235 val = values[i];
237
240 {
241 /*
242 * we're anticipating converting to a short varlena header, so
243 * adjust length and don't count any alignment
244 */
246 }
247 else if (atti->attlen == -1 &&
249 {
250 /*
251 * we want to flatten the expanded value so that the constructed
252 * tuple doesn't depend on it
253 */
254 data_length = att_nominal_alignby(data_length, atti->attalignby);
255 data_length += EOH_get_flat_size(DatumGetEOHP(val));
256 }
257 else
258 {
259 data_length = att_datum_alignby(data_length, atti->attalignby,
260 atti->attlen, val);
261 data_length = att_addlength_datum(data_length, atti->attlen,
262 val);
263 }
264 }
265
266 return data_length;
267}

References att_addlength_datum, att_datum_alignby, att_nominal_alignby, COMPACT_ATTR_IS_PACKABLE, DatumGetEOHP(), DatumGetPointer(), EOH_get_flat_size(), fb(), i, TupleDescCompactAttr(), val, values, VARATT_CAN_MAKE_SHORT(), VARATT_CONVERTED_SHORT_SIZE(), and VARATT_IS_EXTERNAL_EXPANDED().

Referenced by brin_form_tuple(), ER_get_flat_size(), heap_form_minimal_tuple(), heap_form_tuple(), heap_toast_insert_or_update(), index_form_tuple_context(), spgFormLeafTuple(), SpGistGetLeafTupleSize(), and toast_flatten_tuple_to_datum().

◆ heap_copy_minimal_tuple()

MinimalTuple heap_copy_minimal_tuple ( MinimalTuple  mtup,
Size  extra 
)

Definition at line 1490 of file heaptuple.c.

1491{
1492 MinimalTuple result;
1493 char *mem;
1494
1495 Assert(extra == MAXALIGN(extra));
1496 mem = palloc(mtup->t_len + extra);
1497 memset(mem, 0, extra);
1498 result = (MinimalTuple) (mem + extra);
1499 memcpy(result, mtup, mtup->t_len);
1500 return result;
1501}

References Assert, fb(), MAXALIGN, palloc(), and MinimalTupleData::t_len.

Referenced by gm_readnext_tuple(), tts_minimal_copy_minimal_tuple(), tts_minimal_materialize(), tuplesort_gettupleslot(), tuplestore_gettupleslot(), and tuplestore_gettupleslot_force().

◆ heap_copy_tuple_as_datum()

Datum heap_copy_tuple_as_datum ( HeapTuple  tuple,
TupleDesc  tupleDesc 
)

Definition at line 1001 of file heaptuple.c.

1002{
1003 HeapTupleHeader td;
1004
1005 /*
1006 * If the tuple contains any external TOAST pointers, we have to inline
1007 * those fields to meet the conventions for composite-type Datums.
1008 */
1009 if (HeapTupleHasExternal(tuple))
1011 tuple->t_len,
1012 tupleDesc);
1013
1014 /*
1015 * Fast path for easy case: just make a palloc'd copy and insert the
1016 * correct composite-Datum header fields (since those may not be set if
1017 * the given tuple came from disk, rather than from heap_form_tuple).
1018 */
1019 td = (HeapTupleHeader) palloc(tuple->t_len);
1020 memcpy(td, tuple->t_data, tuple->t_len);
1021
1023 HeapTupleHeaderSetTypeId(td, tupleDesc->tdtypeid);
1024 HeapTupleHeaderSetTypMod(td, tupleDesc->tdtypmod);
1025
1026 return PointerGetDatum(td);
1027}

References fb(), HeapTupleHasExternal(), HeapTupleHeaderSetDatumLength(), HeapTupleHeaderSetTypeId(), HeapTupleHeaderSetTypMod(), palloc(), PointerGetDatum(), HeapTupleData::t_data, HeapTupleData::t_len, and toast_flatten_tuple_to_datum().

Referenced by ExecEvalConvertRowtype(), ExecFetchSlotHeapTupleDatum(), import_pg_statistic(), PLyGenericObject_ToComposite(), PLyMapping_ToComposite(), PLySequence_ToComposite(), serialize_expr_stats(), and SPI_returntuple().

◆ heap_copytuple()

HeapTuple heap_copytuple ( HeapTuple  tuple)

Definition at line 698 of file heaptuple.c.

699{
701
702 if (!HeapTupleIsValid(tuple) || tuple->t_data == NULL)
703 return NULL;
704
706 newTuple->t_len = tuple->t_len;
707 newTuple->t_self = tuple->t_self;
708 newTuple->t_tableOid = tuple->t_tableOid;
709 newTuple->t_data = (HeapTupleHeader) ((char *) newTuple + HEAPTUPLESIZE);
710 memcpy(newTuple->t_data, tuple->t_data, tuple->t_len);
711 return newTuple;
712}

References fb(), HeapTupleIsValid, HEAPTUPLESIZE, palloc(), HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, and HeapTupleData::t_tableOid.

Referenced by AlterConstraintNamespaces(), AlterConstrTriggerDeferrability(), AlterConstrUpdateConstraintEntry(), AlterDomainValidateConstraint(), AlterExtensionNamespace(), AlterSequence(), AlterTypeOwner(), changeDependenciesOf(), changeDependenciesOn(), changeDependencyFor(), ConstraintSetParentConstraint(), CopyStatistics(), CreateTriggerFiringOn(), DefineIndex(), dropconstraint_internal(), EnableDisableTrigger(), ExecForceStoreHeapTuple(), expanded_record_set_tuple(), findDomainNotNullConstraint(), findNotNullConstraintAttnum(), get_catalog_object_by_oid_extended(), GetDatabaseTuple(), GetDatabaseTupleByOid(), index_concurrently_swap(), make_expanded_record_from_datum(), MarkInheritDetached(), MergeConstraintsIntoExisting(), MergeWithExistingConstraint(), QueueCheckConstraintValidation(), QueueFKConstraintValidation(), QueueNNConstraintValidation(), RelationInitIndexAccessInfo(), RemoveInheritance(), rename_policy(), RenameEnumLabel(), RenameTableSpace(), renametrig_internal(), RenumberEnumType(), ResetSequence(), rewrite_heap_tuple(), ScanPgRelation(), SearchSysCacheCopy(), SearchSysCacheCopyAttName(), SearchSysCacheCopyAttNum(), SearchSysCacheLockedCopy1(), shdepChangeDep(), SPI_copytuple(), statext_expressions_load(), systable_inplace_update_begin(), TriggerSetParentTrigger(), tts_buffer_heap_copy_heap_tuple(), tts_buffer_heap_materialize(), tts_heap_copy_heap_tuple(), tts_heap_materialize(), and tuplesort_putheaptuple().

◆ heap_copytuple_with_tuple()

void heap_copytuple_with_tuple ( HeapTuple  src,
HeapTuple  dest 
)

Definition at line 724 of file heaptuple.c.

725{
726 if (!HeapTupleIsValid(src) || src->t_data == NULL)
727 {
728 dest->t_data = NULL;
729 return;
730 }
731
732 dest->t_len = src->t_len;
733 dest->t_self = src->t_self;
734 dest->t_tableOid = src->t_tableOid;
735 dest->t_data = (HeapTupleHeader) palloc(src->t_len);
736 memcpy(dest->t_data, src->t_data, src->t_len);
737}

References fb(), HeapTupleIsValid, palloc(), HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, and HeapTupleData::t_tableOid.

◆ heap_deform_tuple()

void heap_deform_tuple ( HeapTuple  tuple,
TupleDesc  tupleDesc,
Datum values,
bool isnull 
)

Definition at line 1266 of file heaptuple.c.

1268{
1269 HeapTupleHeader tup = tuple->t_data;
1271 bool hasnulls = HeapTupleHasNulls(tuple);
1272 int tdesc_natts = tupleDesc->natts;
1273 int natts; /* number of atts to extract */
1274 int attnum;
1275 char *tp; /* ptr to tuple data */
1276 uint32 off; /* offset in tuple data */
1277 bits8 *bp = tup->t_bits; /* ptr to null bitmap in tuple */
1279 int firstNullAttr;
1280
1282
1283 /* Did someone forget to call TupleDescFinalize()? */
1284 Assert(tupleDesc->firstNonCachedOffsetAttr >= 0);
1285
1286 /*
1287 * In inheritance situations, it is possible that the given tuple actually
1288 * has more fields than the caller is expecting. Don't run off the end of
1289 * the caller's arrays.
1290 */
1291 natts = Min(natts, tdesc_natts);
1292 firstNonCacheOffsetAttr = Min(tupleDesc->firstNonCachedOffsetAttr, natts);
1293
1294 if (hasnulls)
1295 {
1297
1298 /*
1299 * XXX: it'd be nice to use populate_isnull_array() here, but that
1300 * requires that the isnull array's size is rounded up to the next
1301 * multiple of 8. Doing that would require adjusting many locations
1302 * that allocate the array.
1303 */
1305 }
1306 else
1307 firstNullAttr = natts;
1308
1309 tp = (char *) tup + tup->t_hoff;
1310 attnum = 0;
1311
1313 {
1314#ifdef USE_ASSERT_CHECKING
1315 /* In Assert enabled builds, verify attcacheoff is correct */
1316 int offcheck = 0;
1317#endif
1318 do
1319 {
1320 isnull[attnum] = false;
1322 off = cattr->attcacheoff;
1323
1324#ifdef USE_ASSERT_CHECKING
1326 Assert(offcheck == cattr->attcacheoff);
1327 offcheck += cattr->attlen;
1328#endif
1329
1330 values[attnum] = fetch_att_noerr(tp + off,
1331 cattr->attbyval,
1332 cattr->attlen);
1333 } while (++attnum < firstNonCacheOffsetAttr);
1334 off += cattr->attlen;
1335 }
1336 else
1337 off = 0;
1338
1339 for (; attnum < firstNullAttr; attnum++)
1340 {
1341 isnull[attnum] = false;
1344 &off,
1345 cattr->attbyval,
1346 cattr->attlen,
1347 cattr->attalignby);
1348 }
1349
1350 for (; attnum < natts; attnum++)
1351 {
1353
1354 if (att_isnull(attnum, bp))
1355 {
1356 values[attnum] = (Datum) 0;
1357 isnull[attnum] = true;
1358 continue;
1359 }
1360
1361 isnull[attnum] = false;
1363
1364 /* align 'off', fetch the attr's value, and increment off beyond it */
1366 &off,
1367 cattr->attbyval,
1368 cattr->attlen,
1369 cattr->attalignby);
1370 }
1371
1372 /*
1373 * If tuple doesn't have all the atts indicated by tupleDesc, read the
1374 * rest as nulls or missing values as appropriate.
1375 */
1376 for (; attnum < tdesc_natts; attnum++)
1378}

References align_fetch_then_add(), Assert, att_isnull(), att_nominal_alignby, attnum, fb(), fetch_att_noerr(), first_null_attr(), getmissingattr(), HeapTupleHasNulls(), HeapTupleHeaderGetNatts, Min, HeapTupleData::t_data, TupleDescCompactAttr(), and values.

Referenced by attribute_statistics_update(), deconstruct_expanded_record(), exec_move_row(), ExecEvalFieldStoreDeForm(), ExecForceStoreHeapTuple(), ExecForceStoreMinimalTuple(), ExecStoreHeapTupleDatum(), execute_attr_map_tuple(), ExtractReplicaIdentity(), hash_record(), hash_record_extended(), heap_modify_tuple(), heap_modify_tuple_by_cols(), heap_toast_delete(), heap_toast_insert_or_update(), hstore_from_record(), hstore_populate_record(), make_tuple_indirect(), populate_record(), record_cmp(), record_eq(), record_image_cmp(), record_image_eq(), record_out(), record_send(), reform_and_rewrite_tuple(), ReorderBufferToastReplace(), RI_Initial_Check(), RI_PartitionRemove_Check(), SPI_modifytuple(), toast_flatten_tuple(), and toast_flatten_tuple_to_datum().

◆ heap_expand_tuple()

HeapTuple heap_expand_tuple ( HeapTuple  sourceTuple,
TupleDesc  tupleDesc 
)

Definition at line 986 of file heaptuple.c.

987{
989
991 return heapTuple;
992}

References expand_tuple(), and fb().

◆ heap_fill_tuple()

void heap_fill_tuple ( TupleDesc  tupleDesc,
const Datum values,
const bool isnull,
char data,
Size  data_size,
uint16 infomask,
bits8 bit 
)

Definition at line 401 of file heaptuple.c.

405{
406 bits8 *bitP;
407 int bitmask;
408 int i;
409 int numberOfAttributes = tupleDesc->natts;
410
411#ifdef USE_ASSERT_CHECKING
412 char *start = data;
413#endif
414
415 if (bit != NULL)
416 {
417 bitP = &bit[-1];
418 bitmask = HIGHBIT;
419 }
420 else
421 {
422 /* just to keep compiler quiet */
423 bitP = NULL;
424 bitmask = 0;
425 }
426
428
429 for (i = 0; i < numberOfAttributes; i++)
430 {
432
433 fill_val(attr,
434 bitP ? &bitP : NULL,
435 &bitmask,
436 &data,
437 infomask,
439 isnull ? isnull[i] : true);
440 }
441
442 Assert((data - start) == data_size);
443}

References Assert, bit(), data, fb(), fill_val(), HEAP_HASEXTERNAL, HEAP_HASNULL, HEAP_HASVARWIDTH, HIGHBIT, i, PointerGetDatum(), start, TupleDescCompactAttr(), and values.

Referenced by brin_form_tuple(), ER_flatten_into(), heap_form_minimal_tuple(), heap_form_tuple(), heap_toast_insert_or_update(), index_form_tuple_context(), spgFormLeafTuple(), and toast_flatten_tuple_to_datum().

◆ heap_form_minimal_tuple()

MinimalTuple heap_form_minimal_tuple ( TupleDesc  tupleDescriptor,
const Datum values,
const bool isnull,
Size  extra 
)

Definition at line 1402 of file heaptuple.c.

1406{
1407 MinimalTuple tuple; /* return tuple */
1408 char *mem;
1409 Size len,
1410 data_len;
1411 int hoff;
1412 bool hasnull = false;
1414 int i;
1415
1416 Assert(extra == MAXALIGN(extra));
1417
1419 ereport(ERROR,
1421 errmsg("number of columns (%d) exceeds limit (%d)",
1423
1424 /*
1425 * Check for nulls
1426 */
1427 for (i = 0; i < numberOfAttributes; i++)
1428 {
1429 if (isnull[i])
1430 {
1431 hasnull = true;
1432 break;
1433 }
1434 }
1435
1436 /*
1437 * Determine total space needed
1438 */
1440
1441 if (hasnull)
1443
1444 hoff = len = MAXALIGN(len); /* align user data safely */
1445
1446 data_len = heap_compute_data_size(tupleDescriptor, values, isnull);
1447
1448 len += data_len;
1449
1450 /*
1451 * Allocate and zero the space needed.
1452 */
1453 mem = palloc0(len + extra);
1454 tuple = (MinimalTuple) (mem + extra);
1455
1456 /*
1457 * And fill in the information.
1458 */
1459 tuple->t_len = len;
1461 tuple->t_hoff = hoff + MINIMAL_TUPLE_OFFSET;
1462
1464 values,
1465 isnull,
1466 (char *) tuple + hoff,
1467 data_len,
1468 &tuple->t_infomask,
1469 (hasnull ? tuple->t_bits : NULL));
1470
1471 return tuple;
1472}

References Assert, BITMAPLEN(), ereport, errcode(), errmsg, ERROR, fb(), heap_compute_data_size(), heap_fill_tuple(), HeapTupleHeaderSetNatts, i, len, MAXALIGN, MaxTupleAttributeNumber, MINIMAL_TUPLE_OFFSET, palloc0(), SizeofMinimalTupleHeader, MinimalTupleData::t_bits, MinimalTupleData::t_hoff, MinimalTupleData::t_infomask, MinimalTupleData::t_len, and values.

Referenced by tts_minimal_materialize(), tts_virtual_copy_minimal_tuple(), and tuplestore_putvalues().

◆ heap_form_tuple()

HeapTuple heap_form_tuple ( TupleDesc  tupleDescriptor,
const Datum values,
const bool isnull 
)

Definition at line 1037 of file heaptuple.c.

1040{
1041 HeapTuple tuple; /* return tuple */
1042 HeapTupleHeader td; /* tuple data */
1043 Size len,
1044 data_len;
1045 int hoff;
1046 bool hasnull = false;
1048 int i;
1049
1051 ereport(ERROR,
1053 errmsg("number of columns (%d) exceeds limit (%d)",
1055
1056 /*
1057 * Check for nulls
1058 */
1059 for (i = 0; i < numberOfAttributes; i++)
1060 {
1061 if (isnull[i])
1062 {
1063 hasnull = true;
1064 break;
1065 }
1066 }
1067
1068 /*
1069 * Determine total space needed
1070 */
1071 len = offsetof(HeapTupleHeaderData, t_bits);
1072
1073 if (hasnull)
1075
1076 hoff = len = MAXALIGN(len); /* align user data safely */
1077
1078 data_len = heap_compute_data_size(tupleDescriptor, values, isnull);
1079
1080 len += data_len;
1081
1082 /*
1083 * Allocate and zero the space needed. Note that the tuple body and
1084 * HeapTupleData management structure are allocated in one chunk.
1085 */
1086 tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + len);
1087 tuple->t_data = td = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE);
1088
1089 /*
1090 * And fill in the information. Note we fill the Datum fields even though
1091 * this tuple may never become a Datum. This lets HeapTupleHeaderGetDatum
1092 * identify the tuple type if needed.
1093 */
1094 tuple->t_len = len;
1095 ItemPointerSetInvalid(&(tuple->t_self));
1096 tuple->t_tableOid = InvalidOid;
1097
1101 /* We also make sure that t_ctid is invalid unless explicitly set */
1103
1105 td->t_hoff = hoff;
1106
1108 values,
1109 isnull,
1110 (char *) td + hoff,
1111 data_len,
1112 &td->t_infomask,
1113 (hasnull ? td->t_bits : NULL));
1114
1115 return tuple;
1116}

References BITMAPLEN(), ereport, errcode(), errmsg, ERROR, fb(), heap_compute_data_size(), heap_fill_tuple(), HeapTupleHeaderSetDatumLength(), HeapTupleHeaderSetNatts, HeapTupleHeaderSetTypeId(), HeapTupleHeaderSetTypMod(), HEAPTUPLESIZE, i, InvalidOid, ItemPointerSetInvalid(), len, MAXALIGN, MaxTupleAttributeNumber, palloc0(), HeapTupleHeaderData::t_bits, HeapTupleHeaderData::t_ctid, HeapTupleData::t_data, HeapTupleHeaderData::t_hoff, HeapTupleHeaderData::t_infomask, HeapTupleData::t_len, HeapTupleData::t_self, HeapTupleData::t_tableOid, and values.

Referenced by aclexplode(), AddEnumLabel(), AddRoleMems(), AddSubscriptionRelState(), AggregateCreate(), AlterSetting(), brin_metapage_info(), bt_page_print_tuples(), BuildTupleFromCStrings(), CastCreate(), CollationCreate(), ConversionCreate(), copy_replication_slot(), CopyToJsonOneRow(), CreateAccessMethod(), CreateComments(), CreateConstraintEntry(), createdb(), CreateForeignDataWrapper(), CreateForeignServer(), CreateForeignTable(), CreateOpFamily(), CreatePolicy(), CreateProceduralLanguage(), CreatePublication(), CreateRole(), CreateSharedComments(), CreateStatistics(), CreateSubscription(), CreateTableSpace(), CreateTransform(), CreateTriggerFiringOn(), CreateUserMapping(), DefineOpClass(), DefineSequence(), DefineTSConfiguration(), DefineTSDictionary(), DefineTSParser(), DefineTSTemplate(), each_object_field_end(), elements_array_element_end(), ExecEvalFieldStoreForm(), ExecEvalRow(), execute_attr_map_tuple(), expanded_record_get_tuple(), ExtractReplicaIdentity(), file_acquire_sample_rows(), fill_hba_line(), fill_ident_line(), gin_leafpage_items(), gin_metapage_info(), gin_page_opaque_info(), gist_page_opaque_info(), gistFetchTuple(), hash_bitmap_info(), hash_metapage_info(), hash_page_items(), hash_page_stats(), heap_modify_tuple(), heap_modify_tuple_by_cols(), heap_page_items(), heap_tuple_infomask_flags(), hstore_each(), hstore_populate_record(), import_pg_statistic(), insert_element_record(), insert_event_trigger_tuple(), insert_label_record(), insert_property_record(), InsertExtensionTuple(), InsertOneTuple(), InsertPgClassTuple(), InsertRule(), inv_truncate(), inv_write(), LargeObjectCreate(), make_tuple_from_result_row(), make_tuple_from_row(), make_tuple_indirect(), NamespaceCreate(), OperatorCreate(), OperatorShellMake(), page_header(), ParameterAclCreate(), pg_available_wal_summaries(), pg_backup_stop(), pg_buffercache_evict(), pg_buffercache_evict_all(), pg_buffercache_evict_relation(), pg_buffercache_mark_dirty(), pg_buffercache_mark_dirty_all(), pg_buffercache_mark_dirty_relation(), pg_buffercache_os_pages_internal(), pg_buffercache_pages(), pg_buffercache_summary(), pg_control_checkpoint(), pg_control_init(), pg_control_recovery(), pg_control_system(), pg_create_logical_replication_slot(), pg_create_physical_replication_slot(), pg_get_catalog_foreign_keys(), pg_get_logical_snapshot_info(), pg_get_logical_snapshot_meta(), pg_get_multixact_stats(), pg_get_object_address(), pg_get_publication_tables(), pg_get_sequence_data(), pg_get_wal_record_info(), pg_get_wal_summarizer_state(), pg_identify_object(), pg_identify_object_as_address(), pg_input_error_info(), pg_last_committed_xact(), pg_lock_status(), pg_partition_tree(), pg_prepared_xact(), pg_replication_slot_advance(), pg_sequence_parameters(), pg_split_walfile_name(), pg_stat_file(), pg_stat_get_archiver(), pg_stat_get_backend_subxact(), pg_stat_get_recovery(), pg_stat_get_replication_slot(), pg_stat_get_subscription_stats(), pg_stat_get_wal_receiver(), pg_stat_statements_info(), pg_stat_wal_build_tuple(), pg_stats_ext_mcvlist_items(), pg_timezone_abbrevs_abbrevs(), pg_timezone_abbrevs_zone(), pg_visibility(), pg_visibility_map(), pg_visibility_map_rel(), pg_visibility_map_summary(), pg_visibility_rel(), pg_wal_summary_contents(), pg_walfile_name_offset(), pg_xact_commit_timestamp_origin(), pgstatginindex_internal(), pgstathashindex(), pgstattuple_approx_internal(), plperl_build_tuple_result(), PLyGenericObject_ToComposite(), PLyMapping_ToComposite(), PLySequence_ToComposite(), populate_record(), ProcedureCreate(), publication_add_relation(), publication_add_schema(), RangeCreate(), record_in(), record_recv(), recordExtensionInitPrivWorker(), reform_and_rewrite_tuple(), ReorderBufferToastReplace(), replorigin_create(), report_corruption_internal(), serialize_expr_stats(), SetDefaultACL(), SetSecurityLabel(), SetSharedSecurityLabel(), shdepAddDependency(), shdepChangeDep(), SPI_modifytuple(), ssl_extension_info(), statext_store(), StoreAttrDefault(), storeGettuple(), storeOperators(), StorePartitionKey(), storeProcedures(), StoreSingleInheritance(), test_custom_stats_fixed_report(), test_custom_stats_var_report(), test_enc_conversion(), test_predtest(), test_saslprep(), test_saslprep_ranges(), toast_build_flattened_tuple(), toast_flatten_tuple(), toast_save_datum(), tsvector_unnest(), tts_buffer_heap_materialize(), tts_heap_materialize(), tts_virtual_copy_heap_tuple(), TypeCreate(), TypeShellMake(), update_attstats(), UpdateIndexRelation(), upsert_pg_statistic(), and upsert_pg_statistic_ext_data().

◆ heap_free_minimal_tuple()

◆ heap_freetuple()

void heap_freetuple ( HeapTuple  htup)

Definition at line 1384 of file heaptuple.c.

1385{
1386 pfree(htup);
1387}

References pfree().

Referenced by acquire_inherited_sample_rows(), acquire_sample_rows(), AddEnumLabel(), AddSubscriptionRelState(), AfterTriggerExecute(), AlterCollation(), AlterConstrTriggerDeferrability(), AlterConstrUpdateConstraintEntry(), AlterDatabaseOwner(), AlterDatabaseRefreshColl(), AlterDomainDefault(), AlterDomainNotNull(), AlterDomainValidateConstraint(), AlterEventTrigger(), AlterEventTriggerOwner(), AlterEventTriggerOwner_oid(), AlterForeignDataWrapper(), AlterForeignDataWrapperOwner(), AlterForeignDataWrapperOwner_oid(), AlterForeignServer(), AlterForeignServerOwner(), AlterForeignServerOwner_oid(), AlterFunction(), AlterObjectRename_internal(), AlterPolicy(), AlterPublication(), AlterPublicationOwner(), AlterPublicationOwner_oid(), AlterRelationNamespaceInternal(), AlterRole(), AlterSchemaOwner_internal(), AlterStatistics(), AlterSubscription(), AlterSubscriptionOwner(), AlterSubscriptionOwner_oid(), AlterTableSpaceOptions(), AlterTSDictionary(), AlterTypeNamespaceInternal(), AlterUserMapping(), analyze_row_processor(), ATExecAddColumn(), ATExecAddIdentity(), ATExecAddOf(), ATExecAlterColumnGenericOptions(), ATExecAlterColumnType(), ATExecAlterConstrInheritability(), ATExecChangeOwner(), ATExecDropColumn(), ATExecDropExpression(), ATExecDropIdentity(), ATExecDropNotNull(), ATExecDropOf(), ATExecForceNoForceRowSecurity(), ATExecGenericOptions(), ATExecSetAccessMethodNoStorage(), ATExecSetCompression(), ATExecSetIdentity(), ATExecSetOptions(), ATExecSetRelOptions(), ATExecSetRowSecurity(), ATExecSetStatistics(), ATExecSetStorage(), ATPrepAddPrimaryKey(), build_tuplestore_recursively(), CastCreate(), CatalogCacheCreateEntry(), CatalogTuplesMultiInsertWithInfo(), change_owner_fix_column_acls(), changeDependenciesOf(), changeDependenciesOn(), changeDependencyFor(), clear_subscription_skip_lsn(), CollationCreate(), ConversionCreate(), copy_table_data(), CopyStatistics(), create_toast_table(), CreateAccessMethod(), CreateComments(), CreateForeignDataWrapper(), CreateForeignServer(), CreateForeignTable(), CreateOpFamily(), CreatePolicy(), CreatePublication(), CreateSharedComments(), CreateStatistics(), CreateSubscription(), CreateTableSpace(), CreateTransform(), CreateTriggerFiringOn(), CreateUserMapping(), crosstab(), DefineIndex(), DefineOpClass(), DefineSequence(), DefineTSConfiguration(), DefineTSDictionary(), DefineTSParser(), DefineTSTemplate(), DetachPartitionFinalize(), DisableSubscription(), dropconstraint_internal(), dropdb(), EnableDisableRule(), EnableDisableTrigger(), EventTriggerOnLogin(), examine_attribute(), examine_attribute(), examine_expression(), ExecBRDeleteTriggers(), ExecBRInsertTriggers(), ExecBRUpdateTriggers(), ExecIRDeleteTriggers(), ExecIRInsertTriggers(), ExecIRUpdateTriggers(), ExecReScanAgg(), ExecReScanIndexScan(), ExecScanSubPlan(), ExecSetParamPlan(), expanded_record_set_tuple(), extended_statistics_update(), ExtractReplicaIdentity(), file_acquire_sample_rows(), heap_delete(), heap_insert(), heap_update(), import_pg_statistic(), index_build(), index_concurrently_swap(), index_constraint_create(), index_update_stats(), insert_element_record(), insert_event_trigger_tuple(), insert_label_record(), insert_property_record(), InsertExtensionTuple(), InsertOneTuple(), InsertPgClassTuple(), InsertRule(), inv_truncate(), inv_write(), LargeObjectCreate(), mark_index_clustered(), MarkInheritDetached(), MergeAttributesIntoExisting(), MergeConstraintsIntoExisting(), OperatorShellMake(), ParameterAclCreate(), pg_clear_extended_stats(), PLyGenericObject_ToComposite(), PLyMapping_ToComposite(), PLySequence_ToComposite(), ProcedureCreate(), publication_add_relation(), publication_add_schema(), QueueCheckConstraintValidation(), QueueFKConstraintValidation(), QueueNNConstraintValidation(), RangeCreate(), raw_heap_insert(), record_in(), record_recv(), reform_and_rewrite_tuple(), relation_mark_replica_identity(), relation_statistics_update(), RelationBuildDesc(), RelationClearMissing(), RelationInitPhysicalAddr(), RelationReloadIndexInfo(), RelationReloadNailed(), RelationSetNewRelfilenumber(), RemoveConstraintById(), RemoveInheritance(), RemoveRoleFromObjectPolicy(), renameatt_internal(), RenameConstraintById(), RenameEnumLabel(), RenameRelationInternal(), RenameRewriteRule(), RenameSchema(), RenameTypeInternal(), RenumberEnumType(), replorigin_create(), ResetRelRewrite(), rewrite_heap_dead_tuple(), rewrite_heap_tuple(), set_attnotnull(), SetDatabaseHasLoginEventTriggers(), SetIndexStorageProperties(), SetMatViewPopulatedState(), SetRelationHasSubclass(), SetRelationNumChecks(), SetRelationRuleStatus(), SetRelationTableSpace(), SetSecurityLabel(), SetSharedSecurityLabel(), shdepAddDependency(), shdepChangeDep(), SPI_freetuple(), statext_store(), StoreAttrDefault(), storeOperators(), StorePartitionBound(), storeProcedures(), StoreSingleInheritance(), swap_relation_files(), table_recheck_autovac(), toast_save_datum(), TriggerSetParentTrigger(), tts_buffer_heap_clear(), tts_buffer_heap_store_tuple(), tts_heap_clear(), TypeShellMake(), update_attstats(), update_default_partition_oid(), update_relispartition(), UpdateDeadTupleRetentionStatus(), UpdateIndexRelation(), UpdateTwoPhaseState(), upsert_pg_statistic(), upsert_pg_statistic_ext_data(), vac_update_datfrozenxid(), validatePartitionedIndex(), and xpath_table().

◆ heap_getsysattr()

Datum heap_getsysattr ( HeapTuple  tup,
int  attnum,
TupleDesc  tupleDesc,
bool isnull 
)

Definition at line 645 of file heaptuple.c.

646{
647 Datum result;
648
649 Assert(tup);
650
651 /* Currently, no sys attribute ever reads as NULL. */
652 *isnull = false;
653
654 switch (attnum)
655 {
657 /* pass-by-reference datatype */
658 result = PointerGetDatum(&(tup->t_self));
659 break;
662 break;
665 break;
668
669 /*
670 * cmin and cmax are now both aliases for the same field, which
671 * can in fact also be a combo command id. XXX perhaps we should
672 * return the "real" cmin or cmax if possible, that is if we are
673 * inside the originating transaction?
674 */
676 break;
678 result = ObjectIdGetDatum(tup->t_tableOid);
679 break;
680 default:
681 elog(ERROR, "invalid attnum: %d", attnum);
682 result = 0; /* keep compiler quiet */
683 break;
684 }
685 return result;
686}

References Assert, attnum, CommandIdGetDatum(), elog, ERROR, fb(), HeapTupleHeaderGetRawCommandId(), HeapTupleHeaderGetRawXmax(), HeapTupleHeaderGetRawXmin(), MaxCommandIdAttributeNumber, MaxTransactionIdAttributeNumber, MinCommandIdAttributeNumber, MinTransactionIdAttributeNumber, ObjectIdGetDatum(), PointerGetDatum(), SelfItemPointerAttributeNumber, TableOidAttributeNumber, and TransactionIdGetDatum().

Referenced by expanded_record_fetch_field(), heap_getattr(), tts_buffer_heap_getsysattr(), and tts_heap_getsysattr().

◆ heap_modify_tuple()

HeapTuple heap_modify_tuple ( HeapTuple  tuple,
TupleDesc  tupleDesc,
const Datum replValues,
const bool replIsnull,
const bool doReplace 
)

Definition at line 1130 of file heaptuple.c.

1135{
1136 int numberOfAttributes = tupleDesc->natts;
1137 int attoff;
1138 Datum *values;
1139 bool *isnull;
1141
1142 /*
1143 * allocate and fill values and isnull arrays from either the tuple or the
1144 * repl information, as appropriate.
1145 *
1146 * NOTE: it's debatable whether to use heap_deform_tuple() here or just
1147 * heap_getattr() only the non-replaced columns. The latter could win if
1148 * there are many replaced columns and few non-replaced ones. However,
1149 * heap_deform_tuple costs only O(N) while the heap_getattr way would cost
1150 * O(N^2) if there are many non-replaced columns, so it seems better to
1151 * err on the side of linear cost.
1152 */
1154 isnull = palloc_array(bool, numberOfAttributes);
1155
1156 heap_deform_tuple(tuple, tupleDesc, values, isnull);
1157
1158 for (attoff = 0; attoff < numberOfAttributes; attoff++)
1159 {
1160 if (doReplace[attoff])
1161 {
1163 isnull[attoff] = replIsnull[attoff];
1164 }
1165 }
1166
1167 /*
1168 * create a new tuple from the values and isnull arrays
1169 */
1171
1172 pfree(values);
1173 pfree(isnull);
1174
1175 /*
1176 * copy the identification info of the old tuple: t_ctid, t_self
1177 */
1178 newTuple->t_data->t_ctid = tuple->t_data->t_ctid;
1179 newTuple->t_self = tuple->t_self;
1180 newTuple->t_tableOid = tuple->t_tableOid;
1181
1182 return newTuple;
1183}

References fb(), heap_deform_tuple(), heap_form_tuple(), palloc_array, pfree(), HeapTupleHeaderData::t_ctid, HeapTupleData::t_data, HeapTupleData::t_self, HeapTupleData::t_tableOid, and values.

Referenced by AddRoleMems(), AggregateCreate(), AlterCollation(), AlterDatabase(), AlterDatabaseOwner(), AlterDatabaseRefreshColl(), AlterDomainDefault(), AlterForeignDataWrapper(), AlterForeignDataWrapperOwner_internal(), AlterForeignServer(), AlterForeignServerOwner_internal(), AlterFunction(), AlterObjectNamespace_internal(), AlterObjectOwner_internal(), AlterObjectRename_internal(), AlterOperator(), AlterPolicy(), AlterPublicationAllFlags(), AlterPublicationOptions(), AlterRole(), AlterSchemaOwner_internal(), AlterSetting(), AlterStatistics(), AlterSubscription(), AlterTableSpaceOptions(), AlterTSDictionary(), AlterTypeOwnerInternal(), AlterTypeRecurse(), AlterUserMapping(), ApplyExtensionUpdates(), ATExecAlterColumnGenericOptions(), ATExecAlterColumnType(), ATExecChangeOwner(), ATExecGenericOptions(), ATExecSetOptions(), ATExecSetRelOptions(), ATExecSetStatistics(), change_owner_fix_column_acls(), clear_subscription_skip_lsn(), CreateComments(), CreateProceduralLanguage(), CreateSharedComments(), CreateTransform(), DelRoleMems(), DetachPartitionFinalize(), DisableSubscription(), ExecGrant_Attribute(), ExecGrant_common(), ExecGrant_Largeobject(), ExecGrant_Parameter(), ExecGrant_Relation(), extension_config_remove(), index_concurrently_swap(), InsertRule(), inv_truncate(), inv_write(), MakeConfigurationMapping(), movedb(), OperatorCreate(), pg_extension_config_dump(), plperl_modify_tuple(), PLy_modify_tuple(), ProcedureCreate(), recordExtensionInitPrivWorker(), RelationClearMissing(), RemoveAttributeById(), RemoveRoleFromInitPriv(), RemoveRoleFromObjectPolicy(), RenameRole(), ReplaceRoleInInitPriv(), SetAttrMissing(), SetDefaultACL(), SetSecurityLabel(), SetSharedSecurityLabel(), StoreAttrDefault(), StoreAttrMissingVal(), StorePartitionBound(), TypeCreate(), update_attstats(), UpdateDeadTupleRetentionStatus(), UpdateSubscriptionRelState(), UpdateTwoPhaseState(), upsert_pg_statistic(), and upsert_pg_statistic_ext_data().

◆ heap_modify_tuple_by_cols()

HeapTuple heap_modify_tuple_by_cols ( HeapTuple  tuple,
TupleDesc  tupleDesc,
int  nCols,
const int replCols,
const Datum replValues,
const bool replIsnull 
)

Definition at line 1198 of file heaptuple.c.

1204{
1205 int numberOfAttributes = tupleDesc->natts;
1206 Datum *values;
1207 bool *isnull;
1209 int i;
1210
1211 /*
1212 * allocate and fill values and isnull arrays from the tuple, then replace
1213 * selected columns from the input arrays.
1214 */
1216 isnull = palloc_array(bool, numberOfAttributes);
1217
1218 heap_deform_tuple(tuple, tupleDesc, values, isnull);
1219
1220 for (i = 0; i < nCols; i++)
1221 {
1222 int attnum = replCols[i];
1223
1225 elog(ERROR, "invalid column number %d", attnum);
1226 values[attnum - 1] = replValues[i];
1227 isnull[attnum - 1] = replIsnull[i];
1228 }
1229
1230 /*
1231 * create a new tuple from the values and isnull arrays
1232 */
1234
1235 pfree(values);
1236 pfree(isnull);
1237
1238 /*
1239 * copy the identification info of the old tuple: t_ctid, t_self
1240 */
1241 newTuple->t_data->t_ctid = tuple->t_data->t_ctid;
1242 newTuple->t_self = tuple->t_self;
1243 newTuple->t_tableOid = tuple->t_tableOid;
1244
1245 return newTuple;
1246}

References attnum, elog, ERROR, fb(), heap_deform_tuple(), heap_form_tuple(), i, palloc_array, pfree(), HeapTupleHeaderData::t_ctid, HeapTupleData::t_data, HeapTupleData::t_self, HeapTupleData::t_tableOid, and values.

Referenced by autoinc(), check_modified_virtual_generated(), insert_username(), moddatetime(), relation_statistics_update(), and tsvector_update_trigger().

◆ heap_tuple_from_minimal_tuple()

HeapTuple heap_tuple_from_minimal_tuple ( MinimalTuple  mtup)

Definition at line 1513 of file heaptuple.c.

1514{
1515 HeapTuple result;
1517
1518 result = (HeapTuple) palloc(HEAPTUPLESIZE + len);
1519 result->t_len = len;
1520 ItemPointerSetInvalid(&(result->t_self));
1521 result->t_tableOid = InvalidOid;
1522 result->t_data = (HeapTupleHeader) ((char *) result + HEAPTUPLESIZE);
1523 memcpy((char *) result->t_data + MINIMAL_TUPLE_OFFSET, mtup, mtup->t_len);
1524 memset(result->t_data, 0, offsetof(HeapTupleHeaderData, t_infomask2));
1525 return result;
1526}

References fb(), HEAPTUPLESIZE, InvalidOid, ItemPointerSetInvalid(), len, MINIMAL_TUPLE_OFFSET, palloc(), HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, and HeapTupleData::t_tableOid.

Referenced by tts_minimal_copy_heap_tuple().

◆ init_missing_cache()

static void init_missing_cache ( void  )
static

Definition at line 126 of file heaptuple.c.

127{
129
131 hash_ctl.entrysize = sizeof(missing_cache_key);
133 hash_ctl.hash = missing_hash;
134 hash_ctl.match = missing_match;
136 hash_create("Missing Values Cache",
137 32,
138 &hash_ctl,
140}

References fb(), HASH_COMPARE, HASH_CONTEXT, hash_create(), HASH_ELEM, HASH_FUNCTION, HASHCTL::keysize, missing_cache, missing_hash(), missing_match(), and TopMemoryContext.

Referenced by getmissingattr().

◆ minimal_expand_tuple()

MinimalTuple minimal_expand_tuple ( HeapTuple  sourceTuple,
TupleDesc  tupleDesc 
)

Definition at line 974 of file heaptuple.c.

References expand_tuple(), and fb().

◆ minimal_tuple_from_heap_tuple()

MinimalTuple minimal_tuple_from_heap_tuple ( HeapTuple  htup,
Size  extra 
)

Definition at line 1535 of file heaptuple.c.

1536{
1537 MinimalTuple result;
1538 char *mem;
1539 uint32 len;
1540
1541 Assert(extra == MAXALIGN(extra));
1543 len = htup->t_len - MINIMAL_TUPLE_OFFSET;
1544 mem = palloc(len + extra);
1545 memset(mem, 0, extra);
1546 result = (MinimalTuple) (mem + extra);
1547 memcpy(result, (char *) htup->t_data + MINIMAL_TUPLE_OFFSET, len);
1548
1549 result->t_len = len;
1550 return result;
1551}

References Assert, fb(), len, MAXALIGN, MINIMAL_TUPLE_OFFSET, palloc(), HeapTupleData::t_data, HeapTupleData::t_len, and MinimalTupleData::t_len.

Referenced by copytup_heap(), tts_buffer_heap_copy_minimal_tuple(), and tts_heap_copy_minimal_tuple().

◆ missing_hash()

static uint32 missing_hash ( const void key,
Size  keysize 
)
static

Definition at line 104 of file heaptuple.c.

105{
106 const missing_cache_key *entry = key;
107
108 return hash_bytes((const unsigned char *) DatumGetPointer(entry->value), entry->len);
109}

References DatumGetPointer(), hash_bytes(), missing_cache_key::len, and missing_cache_key::value.

Referenced by init_missing_cache().

◆ missing_match()

static int missing_match ( const void key1,
const void key2,
Size  keysize 
)
static

Definition at line 112 of file heaptuple.c.

113{
114 const missing_cache_key *entry1 = key1;
116
117 if (entry1->len != entry2->len)
118 return entry1->len > entry2->len ? 1 : -1;
119
120 return memcmp(DatumGetPointer(entry1->value),
121 DatumGetPointer(entry2->value),
122 entry1->len);
123}

References DatumGetPointer(), fb(), missing_cache_key::len, and missing_cache_key::value.

Referenced by init_missing_cache().

◆ nocachegetattr()

Datum nocachegetattr ( HeapTuple  tup,
int  attnum,
TupleDesc  tupleDesc 
)

Definition at line 509 of file heaptuple.c.

512{
514 HeapTupleHeader td = tup->t_data;
515 char *tp; /* ptr to data part of tuple */
516 bits8 *bp = td->t_bits; /* ptr to null bitmap in tuple */
517 int off; /* current offset within data */
518 int startAttr;
519 int firstNullAttr;
520 int i;
522
523 /* Did someone forget to call TupleDescFinalize()? */
524 Assert(tupleDesc->firstNonCachedOffsetAttr >= 0);
525
526 attnum--;
527
528 /*
529 * To minimize the number of attributes we need to look at, start walking
530 * the tuple at the attribute with the highest attcacheoff prior to attnum
531 * or the first NULL attribute prior to attnum, whichever comes first.
532 */
533 if (hasnulls)
535 else
537
538 if (tupleDesc->firstNonCachedOffsetAttr > 0 && firstNullAttr > 0)
539 {
540 /*
541 * Try to start with the highest attribute with an attcacheoff that's
542 * prior to the one we're looking for, or with the attribute prior to
543 * the first NULL attribute, if there is one.
544 */
545 startAttr = Min(tupleDesc->firstNonCachedOffsetAttr - 1, firstNullAttr - 1);
547 }
548 else
549 {
550 /* Otherwise, start at the beginning... */
551 startAttr = 0;
552 off = 0;
553 }
554
555 tp = (char *) td + td->t_hoff;
556
557 /*
558 * Calculate 'off' up to the first NULL attr. We use two cheaper loops
559 * when the tuple has no variable-width columns. When variable-width
560 * columns exists, we use att_addlength_pointer() to move the offset
561 * beyond the current attribute.
562 */
564 {
565 for (i = startAttr; i < firstNullAttr; i++)
566 {
568
569 off = att_nominal_alignby(off, cattr->attalignby);
570 off += cattr->attlen;
571 }
572
573 for (; i < attnum; i++)
574 {
575 if (att_isnull(i, bp))
576 continue;
577
579
580 off = att_nominal_alignby(off, cattr->attalignby);
581 off += cattr->attlen;
582 }
583 }
584 else
585 {
586 for (i = startAttr; i < firstNullAttr; i++)
587 {
588 int attlen;
589
591 attlen = cattr->attlen;
592
593 /*
594 * cstrings don't exist in heap tuples. Use pg_assume to instruct
595 * the compiler not to emit the cstring-related code in
596 * att_addlength_pointer().
597 */
598 pg_assume(attlen > 0 || attlen == -1);
599
600 off = att_pointer_alignby(off,
601 cattr->attalignby,
602 attlen,
603 tp + off);
604 off = att_addlength_pointer(off, attlen, tp + off);
605 }
606
607 for (; i < attnum; i++)
608 {
609 int attlen;
610
611 if (att_isnull(i, bp))
612 continue;
613
615 attlen = cattr->attlen;
616
617 /* As above, heaptuples have no cstrings */
618 pg_assume(attlen > 0 || attlen == -1);
619
620 off = att_pointer_alignby(off, cattr->attalignby, attlen,
621 tp + off);
622 off = att_addlength_pointer(off, attlen, tp + off);
623 }
624 }
625
627 off = att_pointer_alignby(off,
628 cattr->attalignby,
629 cattr->attlen,
630 tp + off);
631
632 return fetchatt(cattr, tp + off);
633}

References Assert, att_addlength_pointer, att_isnull(), att_nominal_alignby, att_pointer_alignby, CompactAttribute::attcacheoff, attlen, attnum, fb(), fetchatt, first_null_attr(), HeapTupleHasNulls(), HeapTupleHasVarWidth(), i, Min, pg_assume, HeapTupleHeaderData::t_bits, HeapTupleHeaderData::t_hoff, and TupleDescCompactAttr().

Referenced by fastgetattr().

◆ varsize_any()

size_t varsize_any ( void p)

Definition at line 1558 of file heaptuple.c.

1559{
1560 return VARSIZE_ANY(p);
1561}

References VARSIZE_ANY().

Variable Documentation

◆ missing_cache

HTAB* missing_cache = NULL
static

Definition at line 101 of file heaptuple.c.

Referenced by getmissingattr(), and init_missing_cache().