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, uint8 **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, uint8 *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{
154 CompactAttribute *att;
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 uint8 **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 uint8 *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 uint8 *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 off = att_pointer_alignby(off,
593 cattr->attalignby,
594 attlen,
595 tp + off);
596 off = att_addlength_pointer(off, attlen, tp + off);
597 }
598
599 for (; i < attnum; i++)
600 {
601 int attlen;
602
603 if (att_isnull(i, bp))
604 continue;
605
607 attlen = cattr->attlen;
608 off = att_pointer_alignby(off, cattr->attalignby, attlen,
609 tp + off);
610 off = att_addlength_pointer(off, attlen, tp + off);
611 }
612 }
613
615 off = att_pointer_alignby(off,
616 cattr->attalignby,
617 cattr->attlen,
618 tp + off);
619
620 return fetchatt(cattr, tp + off);
621}
622
623/* ----------------
624 * heap_getsysattr
625 *
626 * Fetch the value of a system attribute for a tuple.
627 *
628 * This is a support routine for heap_getattr(). The function has already
629 * determined that the attnum refers to a system attribute.
630 * ----------------
631 */
632Datum
634{
636
637 Assert(tup);
638
639 /* Currently, no sys attribute ever reads as NULL. */
640 *isnull = false;
641
642 switch (attnum)
643 {
645 /* pass-by-reference datatype */
646 result = PointerGetDatum(&(tup->t_self));
647 break;
650 break;
653 break;
656
657 /*
658 * cmin and cmax are now both aliases for the same field, which
659 * can in fact also be a combo command id. XXX perhaps we should
660 * return the "real" cmin or cmax if possible, that is if we are
661 * inside the originating transaction?
662 */
664 break;
666 result = ObjectIdGetDatum(tup->t_tableOid);
667 break;
668 default:
669 elog(ERROR, "invalid attnum: %d", attnum);
670 result = 0; /* keep compiler quiet */
671 break;
672 }
673 return result;
674}
675
676/* ----------------
677 * heap_copytuple
678 *
679 * returns a copy of an entire tuple
680 *
681 * The HeapTuple struct, tuple header, and tuple data are all allocated
682 * as a single palloc() block.
683 * ----------------
684 */
687{
689
690 if (!HeapTupleIsValid(tuple) || tuple->t_data == NULL)
691 return NULL;
692
694 newTuple->t_len = tuple->t_len;
695 newTuple->t_self = tuple->t_self;
696 newTuple->t_tableOid = tuple->t_tableOid;
697 newTuple->t_data = (HeapTupleHeader) ((char *) newTuple + HEAPTUPLESIZE);
698 memcpy(newTuple->t_data, tuple->t_data, tuple->t_len);
699 return newTuple;
700}
701
702/* ----------------
703 * heap_copytuple_with_tuple
704 *
705 * copy a tuple into a caller-supplied HeapTuple management struct
706 *
707 * Note that after calling this function, the "dest" HeapTuple will not be
708 * allocated as a single palloc() block (unlike with heap_copytuple()).
709 * ----------------
710 */
711void
713{
714 if (!HeapTupleIsValid(src) || src->t_data == NULL)
715 {
716 dest->t_data = NULL;
717 return;
718 }
719
720 dest->t_len = src->t_len;
721 dest->t_self = src->t_self;
722 dest->t_tableOid = src->t_tableOid;
723 dest->t_data = (HeapTupleHeader) palloc(src->t_len);
724 memcpy(dest->t_data, src->t_data, src->t_len);
725}
726
727/*
728 * Expand a tuple which has fewer attributes than required. For each attribute
729 * not present in the sourceTuple, if there is a missing value that will be
730 * used. Otherwise the attribute will be set to NULL.
731 *
732 * The source tuple must have fewer attributes than the required number.
733 *
734 * Only one of targetHeapTuple and targetMinimalTuple may be supplied. The
735 * other argument must be NULL.
736 */
737static void
742{
744 int attnum;
745 int firstmissingnum;
750 int natts = tupleDesc->natts;
751 int sourceNullLen;
752 int targetNullLen;
753 Size sourceDataLen = sourceTuple->t_len - sourceTHeader->t_hoff;
755 Size len;
756 int hoff;
758 int bitMask = 0;
759 char *targetData;
761
764
765 Assert(sourceNatts < natts);
766
768
770
771 if (tupleDesc->constr &&
772 tupleDesc->constr->missing)
773 {
774 /*
775 * If there are missing values we want to put them into the tuple.
776 * Before that we have to compute the extra length for the values
777 * array and the variable length data.
778 */
779 attrmiss = tupleDesc->constr->missing;
780
781 /*
782 * Find the first item in attrmiss for which we don't have a value in
783 * the source. We can ignore all the missing entries before that.
784 */
786 firstmissingnum < natts;
788 {
789 if (attrmiss[firstmissingnum].am_present)
790 break;
791 else
792 hasNulls = true;
793 }
794
795 /*
796 * Now walk the missing attributes. If there is a missing value make
797 * space for it. Otherwise, it's going to be NULL.
798 */
799 for (attnum = firstmissingnum;
800 attnum < natts;
801 attnum++)
802 {
803 if (attrmiss[attnum].am_present)
804 {
806
808 att->attalignby,
809 att->attlen,
810 attrmiss[attnum].am_value);
811
813 att->attlen,
814 attrmiss[attnum].am_value);
815 }
816 else
817 {
818 /* no missing value, so it must be null */
819 hasNulls = true;
820 }
821 }
822 } /* end if have missing values */
823 else
824 {
825 /*
826 * If there are no missing values at all then NULLS must be allowed,
827 * since some of the attributes are known to be absent.
828 */
829 hasNulls = true;
830 }
831
832 len = 0;
833
834 if (hasNulls)
835 {
836 targetNullLen = BITMAPLEN(natts);
838 }
839 else
840 targetNullLen = 0;
841
842 /*
843 * Allocate and zero the space needed. Note that the tuple body and
844 * HeapTupleData management structure are allocated in one chunk.
845 */
846 if (targetHeapTuple)
847 {
848 len += offsetof(HeapTupleHeaderData, t_bits);
849 hoff = len = MAXALIGN(len); /* align user data safely */
851
853 (*targetHeapTuple)->t_data
856 (*targetHeapTuple)->t_len = len;
857 (*targetHeapTuple)->t_tableOid = sourceTuple->t_tableOid;
858 (*targetHeapTuple)->t_self = sourceTuple->t_self;
859
860 targetTHeader->t_infomask = sourceTHeader->t_infomask;
861 targetTHeader->t_hoff = hoff;
866 /* We also make sure that t_ctid is invalid unless explicitly set */
868 if (targetNullLen > 0)
869 nullBits = (uint8 *) ((char *) (*targetHeapTuple)->t_data
870 + offsetof(HeapTupleHeaderData, t_bits));
871 targetData = (char *) (*targetHeapTuple)->t_data + hoff;
872 infoMask = &(targetTHeader->t_infomask);
873 }
874 else
875 {
877 hoff = len = MAXALIGN(len); /* align user data safely */
879
881 (*targetMinimalTuple)->t_len = len;
882 (*targetMinimalTuple)->t_hoff = hoff + MINIMAL_TUPLE_OFFSET;
883 (*targetMinimalTuple)->t_infomask = sourceTHeader->t_infomask;
884 /* Same macro works for MinimalTuples */
886 if (targetNullLen > 0)
887 nullBits = (uint8 *) ((char *) *targetMinimalTuple
888 + offsetof(MinimalTupleData, t_bits));
889 targetData = (char *) *targetMinimalTuple + hoff;
890 infoMask = &((*targetMinimalTuple)->t_infomask);
891 }
892
893 if (targetNullLen > 0)
894 {
895 if (sourceNullLen > 0)
896 {
897 /* if bitmap pre-existed copy in - all is set */
899 ((char *) sourceTHeader)
900 + offsetof(HeapTupleHeaderData, t_bits),
902 nullBits += sourceNullLen - 1;
903 }
904 else
905 {
907 /* Set NOT NULL for all existing attributes */
909
910 nullBits += sourceNullLen - 1;
911
912 if (sourceNatts & 0x07)
913 {
914 /* build the mask (inverted!) */
915 bitMask = 0xff << (sourceNatts & 0x07);
916 /* Voila */
918 }
919 }
920
921 bitMask = (1 << ((sourceNatts - 1) & 0x07));
922 } /* End if have null bitmap */
923
925 ((char *) sourceTuple->t_data) + sourceTHeader->t_hoff,
927
929
930 /* Now fill in the missing values */
931 for (attnum = sourceNatts; attnum < natts; attnum++)
932 {
934
935 if (attrmiss && attrmiss[attnum].am_present)
936 {
937 fill_val(attr,
939 &bitMask,
940 &targetData,
941 infoMask,
942 attrmiss[attnum].am_value,
943 false);
944 }
945 else
946 {
947 fill_val(attr,
948 &nullBits,
949 &bitMask,
950 &targetData,
951 infoMask,
952 (Datum) 0,
953 true);
954 }
955 } /* end loop over missing attributes */
956}
957
958/*
959 * Fill in the missing values for a minimal HeapTuple
960 */
963{
965
967 return minimalTuple;
968}
969
970/*
971 * Fill in the missing values for an ordinary HeapTuple
972 */
975{
977
979 return heapTuple;
980}
981
982/* ----------------
983 * heap_copy_tuple_as_datum
984 *
985 * copy a tuple as a composite-type Datum
986 * ----------------
987 */
988Datum
990{
992
993 /*
994 * If the tuple contains any external TOAST pointers, we have to inline
995 * those fields to meet the conventions for composite-type Datums.
996 */
997 if (HeapTupleHasExternal(tuple))
999 tuple->t_len,
1000 tupleDesc);
1001
1002 /*
1003 * Fast path for easy case: just make a palloc'd copy and insert the
1004 * correct composite-Datum header fields (since those may not be set if
1005 * the given tuple came from disk, rather than from heap_form_tuple).
1006 */
1007 td = (HeapTupleHeader) palloc(tuple->t_len);
1008 memcpy(td, tuple->t_data, tuple->t_len);
1009
1011 HeapTupleHeaderSetTypeId(td, tupleDesc->tdtypeid);
1012 HeapTupleHeaderSetTypMod(td, tupleDesc->tdtypmod);
1013
1014 return PointerGetDatum(td);
1015}
1016
1017/*
1018 * heap_form_tuple
1019 * construct a tuple from the given values[] and isnull[] arrays,
1020 * which are of the length indicated by tupleDescriptor->natts
1021 *
1022 * The result is allocated in the current memory context.
1023 */
1026 const Datum *values,
1027 const bool *isnull)
1028{
1029 HeapTuple tuple; /* return tuple */
1030 HeapTupleHeader td; /* tuple data */
1031 Size len,
1032 data_len;
1033 int hoff;
1034 bool hasnull = false;
1036 int i;
1037
1039 ereport(ERROR,
1041 errmsg("number of columns (%d) exceeds limit (%d)",
1043
1044 /*
1045 * Check for nulls
1046 */
1047 for (i = 0; i < numberOfAttributes; i++)
1048 {
1049 if (isnull[i])
1050 {
1051 hasnull = true;
1052 break;
1053 }
1054 }
1055
1056 /*
1057 * Determine total space needed
1058 */
1059 len = offsetof(HeapTupleHeaderData, t_bits);
1060
1061 if (hasnull)
1063
1064 hoff = len = MAXALIGN(len); /* align user data safely */
1065
1066 data_len = heap_compute_data_size(tupleDescriptor, values, isnull);
1067
1068 len += data_len;
1069
1070 /*
1071 * Allocate and zero the space needed. Note that the tuple body and
1072 * HeapTupleData management structure are allocated in one chunk.
1073 */
1074 tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + len);
1075 tuple->t_data = td = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE);
1076
1077 /*
1078 * And fill in the information. Note we fill the Datum fields even though
1079 * this tuple may never become a Datum. This lets HeapTupleHeaderGetDatum
1080 * identify the tuple type if needed.
1081 */
1082 tuple->t_len = len;
1083 ItemPointerSetInvalid(&(tuple->t_self));
1084 tuple->t_tableOid = InvalidOid;
1085
1089 /* We also make sure that t_ctid is invalid unless explicitly set */
1091
1093 td->t_hoff = hoff;
1094
1096 values,
1097 isnull,
1098 (char *) td + hoff,
1099 data_len,
1100 &td->t_infomask,
1101 (hasnull ? td->t_bits : NULL));
1102
1103 return tuple;
1104}
1105
1106/*
1107 * heap_modify_tuple
1108 * form a new tuple from an old tuple and a set of replacement values.
1109 *
1110 * The replValues, replIsnull, and doReplace arrays must be of the length
1111 * indicated by tupleDesc->natts. The new tuple is constructed using the data
1112 * from replValues/replIsnull at columns where doReplace is true, and using
1113 * the data from the old tuple at columns where doReplace is false.
1114 *
1115 * The result is allocated in the current memory context.
1116 */
1120 const Datum *replValues,
1121 const bool *replIsnull,
1122 const bool *doReplace)
1123{
1124 int numberOfAttributes = tupleDesc->natts;
1125 int attoff;
1126 Datum *values;
1127 bool *isnull;
1129
1130 /*
1131 * allocate and fill values and isnull arrays from either the tuple or the
1132 * repl information, as appropriate.
1133 *
1134 * NOTE: it's debatable whether to use heap_deform_tuple() here or just
1135 * heap_getattr() only the non-replaced columns. The latter could win if
1136 * there are many replaced columns and few non-replaced ones. However,
1137 * heap_deform_tuple costs only O(N) while the heap_getattr way would cost
1138 * O(N^2) if there are many non-replaced columns, so it seems better to
1139 * err on the side of linear cost.
1140 */
1142 isnull = palloc_array(bool, numberOfAttributes);
1143
1144 heap_deform_tuple(tuple, tupleDesc, values, isnull);
1145
1146 for (attoff = 0; attoff < numberOfAttributes; attoff++)
1147 {
1148 if (doReplace[attoff])
1149 {
1151 isnull[attoff] = replIsnull[attoff];
1152 }
1153 }
1154
1155 /*
1156 * create a new tuple from the values and isnull arrays
1157 */
1159
1160 pfree(values);
1161 pfree(isnull);
1162
1163 /*
1164 * copy the identification info of the old tuple: t_ctid, t_self
1165 */
1166 newTuple->t_data->t_ctid = tuple->t_data->t_ctid;
1167 newTuple->t_self = tuple->t_self;
1168 newTuple->t_tableOid = tuple->t_tableOid;
1169
1170 return newTuple;
1171}
1172
1173/*
1174 * heap_modify_tuple_by_cols
1175 * form a new tuple from an old tuple and a set of replacement values.
1176 *
1177 * This is like heap_modify_tuple, except that instead of specifying which
1178 * column(s) to replace by a boolean map, an array of target column numbers
1179 * is used. This is often more convenient when a fixed number of columns
1180 * are to be replaced. The replCols, replValues, and replIsnull arrays must
1181 * be of length nCols. Target column numbers are indexed from 1.
1182 *
1183 * The result is allocated in the current memory context.
1184 */
1188 int nCols,
1189 const int *replCols,
1190 const Datum *replValues,
1191 const bool *replIsnull)
1192{
1193 int numberOfAttributes = tupleDesc->natts;
1194 Datum *values;
1195 bool *isnull;
1197 int i;
1198
1199 /*
1200 * allocate and fill values and isnull arrays from the tuple, then replace
1201 * selected columns from the input arrays.
1202 */
1204 isnull = palloc_array(bool, numberOfAttributes);
1205
1206 heap_deform_tuple(tuple, tupleDesc, values, isnull);
1207
1208 for (i = 0; i < nCols; i++)
1209 {
1210 int attnum = replCols[i];
1211
1213 elog(ERROR, "invalid column number %d", attnum);
1214 values[attnum - 1] = replValues[i];
1215 isnull[attnum - 1] = replIsnull[i];
1216 }
1217
1218 /*
1219 * create a new tuple from the values and isnull arrays
1220 */
1222
1223 pfree(values);
1224 pfree(isnull);
1225
1226 /*
1227 * copy the identification info of the old tuple: t_ctid, t_self
1228 */
1229 newTuple->t_data->t_ctid = tuple->t_data->t_ctid;
1230 newTuple->t_self = tuple->t_self;
1231 newTuple->t_tableOid = tuple->t_tableOid;
1232
1233 return newTuple;
1234}
1235
1236/*
1237 * heap_deform_tuple
1238 * Given a tuple, extract data into values/isnull arrays; this is
1239 * the inverse of heap_form_tuple.
1240 *
1241 * Storage for the values/isnull arrays is provided by the caller;
1242 * it should be sized according to tupleDesc->natts not
1243 * HeapTupleHeaderGetNatts(tuple->t_data).
1244 *
1245 * Note that for pass-by-reference datatypes, the pointer placed
1246 * in the Datum will point into the given tuple.
1247 *
1248 * When all or most of a tuple's fields need to be extracted,
1249 * this routine will be significantly quicker than a loop around
1250 * heap_getattr; the loop will become O(N^2) as soon as any
1251 * noncacheable attribute offsets are involved.
1252 */
1253void
1255 Datum *values, bool *isnull)
1256{
1257 HeapTupleHeader tup = tuple->t_data;
1259 bool hasnulls = HeapTupleHasNulls(tuple);
1260 int tdesc_natts = tupleDesc->natts;
1261 int natts; /* number of atts to extract */
1262 int attnum;
1263 char *tp; /* ptr to tuple data */
1264 uint32 off; /* offset in tuple data */
1265 uint8 *bp = tup->t_bits; /* ptr to null bitmap in tuple */
1267 int firstNullAttr;
1268
1270
1271 /* Did someone forget to call TupleDescFinalize()? */
1272 Assert(tupleDesc->firstNonCachedOffsetAttr >= 0);
1273
1274 /*
1275 * In inheritance situations, it is possible that the given tuple actually
1276 * has more fields than the caller is expecting. Don't run off the end of
1277 * the caller's arrays.
1278 */
1279 natts = Min(natts, tdesc_natts);
1280 firstNonCacheOffsetAttr = Min(tupleDesc->firstNonCachedOffsetAttr, natts);
1281
1282 if (hasnulls)
1283 {
1285
1286 /*
1287 * XXX: it'd be nice to use populate_isnull_array() here, but that
1288 * requires that the isnull array's size is rounded up to the next
1289 * multiple of 8. Doing that would require adjusting many locations
1290 * that allocate the array.
1291 */
1293 }
1294 else
1295 firstNullAttr = natts;
1296
1297 tp = (char *) tup + tup->t_hoff;
1298 attnum = 0;
1299
1301 {
1302#ifdef USE_ASSERT_CHECKING
1303 /* In Assert enabled builds, verify attcacheoff is correct */
1304 int offcheck = 0;
1305#endif
1306 do
1307 {
1308 isnull[attnum] = false;
1310 off = cattr->attcacheoff;
1311
1312#ifdef USE_ASSERT_CHECKING
1314 Assert(offcheck == cattr->attcacheoff);
1315 offcheck += cattr->attlen;
1316#endif
1317
1318 values[attnum] = fetch_att_noerr(tp + off,
1319 cattr->attbyval,
1320 cattr->attlen);
1321 } while (++attnum < firstNonCacheOffsetAttr);
1322 off += cattr->attlen;
1323 }
1324 else
1325 off = 0;
1326
1327 for (; attnum < firstNullAttr; attnum++)
1328 {
1329 isnull[attnum] = false;
1332 &off,
1333 cattr->attbyval,
1334 cattr->attlen,
1335 cattr->attalignby);
1336 }
1337
1338 for (; attnum < natts; attnum++)
1339 {
1341
1342 if (att_isnull(attnum, bp))
1343 {
1344 values[attnum] = (Datum) 0;
1345 isnull[attnum] = true;
1346 continue;
1347 }
1348
1349 isnull[attnum] = false;
1351
1352 /* align 'off', fetch the attr's value, and increment off beyond it */
1354 &off,
1355 cattr->attbyval,
1356 cattr->attlen,
1357 cattr->attalignby);
1358 }
1359
1360 /*
1361 * If tuple doesn't have all the atts indicated by tupleDesc, read the
1362 * rest as nulls or missing values as appropriate.
1363 */
1364 for (; attnum < tdesc_natts; attnum++)
1366}
1367
1368/*
1369 * heap_freetuple
1370 */
1371void
1373{
1374 pfree(htup);
1375}
1376
1377
1378/*
1379 * heap_form_minimal_tuple
1380 * construct a MinimalTuple from the given values[] and isnull[] arrays,
1381 * which are of the length indicated by tupleDescriptor->natts
1382 *
1383 * This is exactly like heap_form_tuple() except that the result is a
1384 * "minimal" tuple lacking a HeapTupleData header as well as room for system
1385 * columns.
1386 *
1387 * The result is allocated in the current memory context.
1388 */
1391 const Datum *values,
1392 const bool *isnull,
1393 Size extra)
1394{
1395 MinimalTuple tuple; /* return tuple */
1396 char *mem;
1397 Size len,
1398 data_len;
1399 int hoff;
1400 bool hasnull = false;
1402 int i;
1403
1404 Assert(extra == MAXALIGN(extra));
1405
1407 ereport(ERROR,
1409 errmsg("number of columns (%d) exceeds limit (%d)",
1411
1412 /*
1413 * Check for nulls
1414 */
1415 for (i = 0; i < numberOfAttributes; i++)
1416 {
1417 if (isnull[i])
1418 {
1419 hasnull = true;
1420 break;
1421 }
1422 }
1423
1424 /*
1425 * Determine total space needed
1426 */
1428
1429 if (hasnull)
1431
1432 hoff = len = MAXALIGN(len); /* align user data safely */
1433
1434 data_len = heap_compute_data_size(tupleDescriptor, values, isnull);
1435
1436 len += data_len;
1437
1438 /*
1439 * Allocate and zero the space needed.
1440 */
1441 mem = palloc0(len + extra);
1442 tuple = (MinimalTuple) (mem + extra);
1443
1444 /*
1445 * And fill in the information.
1446 */
1447 tuple->t_len = len;
1449 tuple->t_hoff = hoff + MINIMAL_TUPLE_OFFSET;
1450
1452 values,
1453 isnull,
1454 (char *) tuple + hoff,
1455 data_len,
1456 &tuple->t_infomask,
1457 (hasnull ? tuple->t_bits : NULL));
1458
1459 return tuple;
1460}
1461
1462/*
1463 * heap_free_minimal_tuple
1464 */
1465void
1467{
1468 pfree(mtup);
1469}
1470
1471/*
1472 * heap_copy_minimal_tuple
1473 * copy a MinimalTuple
1474 *
1475 * The result is allocated in the current memory context.
1476 */
1479{
1481 char *mem;
1482
1483 Assert(extra == MAXALIGN(extra));
1484 mem = palloc(mtup->t_len + extra);
1485 memset(mem, 0, extra);
1486 result = (MinimalTuple) (mem + extra);
1487 memcpy(result, mtup, mtup->t_len);
1488 return result;
1489}
1490
1491/*
1492 * heap_tuple_from_minimal_tuple
1493 * create a HeapTuple by copying from a MinimalTuple;
1494 * system columns are filled with zeroes
1495 *
1496 * The result is allocated in the current memory context.
1497 * The HeapTuple struct, tuple header, and tuple data are all allocated
1498 * as a single palloc() block.
1499 */
1502{
1505
1507 result->t_len = len;
1508 ItemPointerSetInvalid(&(result->t_self));
1509 result->t_tableOid = InvalidOid;
1510 result->t_data = (HeapTupleHeader) ((char *) result + HEAPTUPLESIZE);
1511 memcpy((char *) result->t_data + MINIMAL_TUPLE_OFFSET, mtup, mtup->t_len);
1512 memset(result->t_data, 0, offsetof(HeapTupleHeaderData, t_infomask2));
1513 return result;
1514}
1515
1516/*
1517 * minimal_tuple_from_heap_tuple
1518 * create a MinimalTuple by copying from a HeapTuple
1519 *
1520 * The result is allocated in the current memory context.
1521 */
1524{
1526 char *mem;
1527 uint32 len;
1528
1529 Assert(extra == MAXALIGN(extra));
1531 len = htup->t_len - MINIMAL_TUPLE_OFFSET;
1532 mem = palloc(len + extra);
1533 memset(mem, 0, extra);
1534 result = (MinimalTuple) (mem + extra);
1535 memcpy(result, (char *) htup->t_data + MINIMAL_TUPLE_OFFSET, len);
1536
1537 result->t_len = len;
1538 return result;
1539}
1540
1541/*
1542 * This mainly exists so JIT can inline the definition, but it's also
1543 * sometimes useful in debugging sessions.
1544 */
1545size_t
1546varsize_any(void *p)
1547{
1548 return VARSIZE_ANY(p);
1549}
static Datum values[MAXATTR]
Definition bootstrap.c:190
#define Min(x, y)
Definition c.h:1091
#define MAXALIGN(LEN)
Definition c.h:896
uint8_t uint8
Definition c.h:622
#define Assert(condition)
Definition c.h:943
uint16_t uint16
Definition c.h:623
uint32_t uint32
Definition c.h:624
void * Pointer
Definition c.h:615
#define HIGHBIT
Definition c.h:1243
size_t Size
Definition c.h:689
uint32 result
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
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:889
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
Definition dynahash.c:360
int errcode(int sqlerrcode)
Definition elog.c:874
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
#define ereport(elevel,...)
Definition elog.h:152
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:1118
void heap_copytuple_with_tuple(HeapTuple src, HeapTuple dest)
Definition heaptuple.c:712
HeapTuple heap_copytuple(HeapTuple tuple)
Definition heaptuple.c:686
size_t varsize_any(void *p)
Definition heaptuple.c:1546
MinimalTuple heap_copy_minimal_tuple(MinimalTuple mtup, Size extra)
Definition heaptuple.c:1478
Datum heap_getsysattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition heaptuple.c:633
MinimalTuple heap_form_minimal_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull, Size extra)
Definition heaptuple.c:1390
void heap_fill_tuple(TupleDesc tupleDesc, const Datum *values, const bool *isnull, char *data, Size data_size, uint16 *infomask, uint8 *bit)
Definition heaptuple.c:401
HeapTuple heap_modify_tuple_by_cols(HeapTuple tuple, TupleDesc tupleDesc, int nCols, const int *replCols, const Datum *replValues, const bool *replIsnull)
Definition heaptuple.c:1186
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition heaptuple.c:1025
void heap_free_minimal_tuple(MinimalTuple mtup)
Definition heaptuple.c:1466
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:1523
HeapTuple heap_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc)
Definition heaptuple.c:974
#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:1254
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:989
static HTAB * missing_cache
Definition heaptuple.c:101
static void expand_tuple(HeapTuple *targetHeapTuple, MinimalTuple *targetMinimalTuple, HeapTuple sourceTuple, TupleDesc tupleDesc)
Definition heaptuple.c:738
static void fill_val(CompactAttribute *att, uint8 **bit, int *bitmask, char **dataP, uint16 *infomask, Datum datum, bool isnull)
Definition heaptuple.c:275
HeapTuple heap_tuple_from_minimal_tuple(MinimalTuple mtup)
Definition heaptuple.c:1501
MinimalTuple minimal_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc)
Definition heaptuple.c:962
void heap_freetuple(HeapTuple htup)
Definition heaptuple.c:1372
@ HASH_ENTER
Definition hsearch.h:109
#define HASH_CONTEXT
Definition hsearch.h:97
#define HASH_ELEM
Definition hsearch.h:90
#define HASH_COMPARE
Definition hsearch.h:94
#define HASH_FUNCTION
Definition hsearch.h:93
#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 @177 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
uint8 attalignby
Definition tupdesc.h:74
bool attispackable
Definition tupdesc.h:75
bool atthasmissing
Definition tupdesc.h:77
Size keysize
Definition hsearch.h:69
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
uint8 t_bits[FLEXIBLE_ARRAY_MEMBER]
ItemPointerData t_ctid
uint8 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:195
#define att_nominal_alignby(cur_offset, attalignby)
Definition tupmacs.h:411
#define att_datum_alignby(cur_offset, attalignby, attlen, attdatum)
Definition tupmacs.h:352
#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 int first_null_attr(const uint8 *bits, int natts)
Definition tupmacs.h:244
static bool att_isnull(int ATT, const uint8 *BITS)
Definition tupmacs.h:28
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 738 of file heaptuple.c.

742{
744 int attnum;
745 int firstmissingnum;
750 int natts = tupleDesc->natts;
751 int sourceNullLen;
752 int targetNullLen;
753 Size sourceDataLen = sourceTuple->t_len - sourceTHeader->t_hoff;
755 Size len;
756 int hoff;
758 int bitMask = 0;
759 char *targetData;
761
764
765 Assert(sourceNatts < natts);
766
768
770
771 if (tupleDesc->constr &&
772 tupleDesc->constr->missing)
773 {
774 /*
775 * If there are missing values we want to put them into the tuple.
776 * Before that we have to compute the extra length for the values
777 * array and the variable length data.
778 */
779 attrmiss = tupleDesc->constr->missing;
780
781 /*
782 * Find the first item in attrmiss for which we don't have a value in
783 * the source. We can ignore all the missing entries before that.
784 */
786 firstmissingnum < natts;
788 {
789 if (attrmiss[firstmissingnum].am_present)
790 break;
791 else
792 hasNulls = true;
793 }
794
795 /*
796 * Now walk the missing attributes. If there is a missing value make
797 * space for it. Otherwise, it's going to be NULL.
798 */
799 for (attnum = firstmissingnum;
800 attnum < natts;
801 attnum++)
802 {
803 if (attrmiss[attnum].am_present)
804 {
806
808 att->attalignby,
809 att->attlen,
810 attrmiss[attnum].am_value);
811
813 att->attlen,
814 attrmiss[attnum].am_value);
815 }
816 else
817 {
818 /* no missing value, so it must be null */
819 hasNulls = true;
820 }
821 }
822 } /* end if have missing values */
823 else
824 {
825 /*
826 * If there are no missing values at all then NULLS must be allowed,
827 * since some of the attributes are known to be absent.
828 */
829 hasNulls = true;
830 }
831
832 len = 0;
833
834 if (hasNulls)
835 {
836 targetNullLen = BITMAPLEN(natts);
838 }
839 else
840 targetNullLen = 0;
841
842 /*
843 * Allocate and zero the space needed. Note that the tuple body and
844 * HeapTupleData management structure are allocated in one chunk.
845 */
846 if (targetHeapTuple)
847 {
848 len += offsetof(HeapTupleHeaderData, t_bits);
849 hoff = len = MAXALIGN(len); /* align user data safely */
851
853 (*targetHeapTuple)->t_data
856 (*targetHeapTuple)->t_len = len;
857 (*targetHeapTuple)->t_tableOid = sourceTuple->t_tableOid;
858 (*targetHeapTuple)->t_self = sourceTuple->t_self;
859
860 targetTHeader->t_infomask = sourceTHeader->t_infomask;
861 targetTHeader->t_hoff = hoff;
866 /* We also make sure that t_ctid is invalid unless explicitly set */
868 if (targetNullLen > 0)
869 nullBits = (uint8 *) ((char *) (*targetHeapTuple)->t_data
870 + offsetof(HeapTupleHeaderData, t_bits));
871 targetData = (char *) (*targetHeapTuple)->t_data + hoff;
872 infoMask = &(targetTHeader->t_infomask);
873 }
874 else
875 {
877 hoff = len = MAXALIGN(len); /* align user data safely */
879
881 (*targetMinimalTuple)->t_len = len;
882 (*targetMinimalTuple)->t_hoff = hoff + MINIMAL_TUPLE_OFFSET;
883 (*targetMinimalTuple)->t_infomask = sourceTHeader->t_infomask;
884 /* Same macro works for MinimalTuples */
886 if (targetNullLen > 0)
887 nullBits = (uint8 *) ((char *) *targetMinimalTuple
888 + offsetof(MinimalTupleData, t_bits));
889 targetData = (char *) *targetMinimalTuple + hoff;
890 infoMask = &((*targetMinimalTuple)->t_infomask);
891 }
892
893 if (targetNullLen > 0)
894 {
895 if (sourceNullLen > 0)
896 {
897 /* if bitmap pre-existed copy in - all is set */
899 ((char *) sourceTHeader)
900 + offsetof(HeapTupleHeaderData, t_bits),
902 nullBits += sourceNullLen - 1;
903 }
904 else
905 {
907 /* Set NOT NULL for all existing attributes */
909
910 nullBits += sourceNullLen - 1;
911
912 if (sourceNatts & 0x07)
913 {
914 /* build the mask (inverted!) */
915 bitMask = 0xff << (sourceNatts & 0x07);
916 /* Voila */
918 }
919 }
920
921 bitMask = (1 << ((sourceNatts - 1) & 0x07));
922 } /* End if have null bitmap */
923
925 ((char *) sourceTuple->t_data) + sourceTHeader->t_hoff,
927
929
930 /* Now fill in the missing values */
931 for (attnum = sourceNatts; attnum < natts; attnum++)
932 {
934
935 if (attrmiss && attrmiss[attnum].am_present)
936 {
937 fill_val(attr,
939 &bitMask,
940 &targetData,
941 infoMask,
942 attrmiss[attnum].am_value,
943 false);
944 }
945 else
946 {
947 fill_val(attr,
948 &nullBits,
949 &bitMask,
950 &targetData,
951 infoMask,
952 (Datum) 0,
953 true);
954 }
955 } /* end loop over missing attributes */
956}

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

Referenced by heap_expand_tuple(), and minimal_expand_tuple().

◆ fill_val()

static void fill_val ( CompactAttribute att,
uint8 **  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, CompactAttribute::attalignby, CompactAttribute::attbyval, CompactAttribute::attispackable, CompactAttribute::attlen, bit(), data, DatumGetCString(), DatumGetEOHP(), DatumGetPointer(), EOH_flatten_into(), EOH_get_flat_size(), fb(), HEAP_HASEXTERNAL, HEAP_HASNULL, HEAP_HASVARWIDTH, HIGHBIT, memcpy(), 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{
154 CompactAttribute *att;
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, CompactAttribute::attbyval, CompactAttribute::atthasmissing, CompactAttribute::attlen, 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(), reform_tuple(), 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 1478 of file heaptuple.c.

1479{
1481 char *mem;
1482
1483 Assert(extra == MAXALIGN(extra));
1484 mem = palloc(mtup->t_len + extra);
1485 memset(mem, 0, extra);
1486 result = (MinimalTuple) (mem + extra);
1487 memcpy(result, mtup, mtup->t_len);
1488 return result;
1489}

References Assert, fb(), MAXALIGN, memcpy(), palloc(), and result.

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 989 of file heaptuple.c.

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

References fb(), HeapTupleHasExternal(), HeapTupleHeaderSetDatumLength(), HeapTupleHeaderSetTypeId(), HeapTupleHeaderSetTypMod(), memcpy(), 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 686 of file heaptuple.c.

687{
689
690 if (!HeapTupleIsValid(tuple) || tuple->t_data == NULL)
691 return NULL;
692
694 newTuple->t_len = tuple->t_len;
695 newTuple->t_self = tuple->t_self;
696 newTuple->t_tableOid = tuple->t_tableOid;
697 newTuple->t_data = (HeapTupleHeader) ((char *) newTuple + HEAPTUPLESIZE);
698 memcpy(newTuple->t_data, tuple->t_data, tuple->t_len);
699 return newTuple;
700}

References fb(), HeapTupleIsValid, HEAPTUPLESIZE, memcpy(), 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(), reform_tuple(), 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 712 of file heaptuple.c.

713{
714 if (!HeapTupleIsValid(src) || src->t_data == NULL)
715 {
716 dest->t_data = NULL;
717 return;
718 }
719
720 dest->t_len = src->t_len;
721 dest->t_self = src->t_self;
722 dest->t_tableOid = src->t_tableOid;
723 dest->t_data = (HeapTupleHeader) palloc(src->t_len);
724 memcpy(dest->t_data, src->t_data, src->t_len);
725}

References fb(), HeapTupleIsValid, memcpy(), 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 1254 of file heaptuple.c.

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

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_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 974 of file heaptuple.c.

975{
977
979 return heapTuple;
980}

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,
uint8 bit 
)

Definition at line 401 of file heaptuple.c.

405{
406 uint8 *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 1390 of file heaptuple.c.

1394{
1395 MinimalTuple tuple; /* return tuple */
1396 char *mem;
1397 Size len,
1398 data_len;
1399 int hoff;
1400 bool hasnull = false;
1402 int i;
1403
1404 Assert(extra == MAXALIGN(extra));
1405
1407 ereport(ERROR,
1409 errmsg("number of columns (%d) exceeds limit (%d)",
1411
1412 /*
1413 * Check for nulls
1414 */
1415 for (i = 0; i < numberOfAttributes; i++)
1416 {
1417 if (isnull[i])
1418 {
1419 hasnull = true;
1420 break;
1421 }
1422 }
1423
1424 /*
1425 * Determine total space needed
1426 */
1428
1429 if (hasnull)
1431
1432 hoff = len = MAXALIGN(len); /* align user data safely */
1433
1434 data_len = heap_compute_data_size(tupleDescriptor, values, isnull);
1435
1436 len += data_len;
1437
1438 /*
1439 * Allocate and zero the space needed.
1440 */
1441 mem = palloc0(len + extra);
1442 tuple = (MinimalTuple) (mem + extra);
1443
1444 /*
1445 * And fill in the information.
1446 */
1447 tuple->t_len = len;
1449 tuple->t_hoff = hoff + MINIMAL_TUPLE_OFFSET;
1450
1452 values,
1453 isnull,
1454 (char *) tuple + hoff,
1455 data_len,
1456 &tuple->t_infomask,
1457 (hasnull ? tuple->t_bits : NULL));
1458
1459 return tuple;
1460}

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 1025 of file heaptuple.c.

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

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_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_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 1372 of file heaptuple.c.

1373{
1374 pfree(htup);
1375}

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(), ExecForPortionOfLeftovers(), ExecIRDeleteTriggers(), ExecIRInsertTriggers(), ExecIRUpdateTriggers(), ExecReScanAgg(), ExecReScanIndexScan(), ExecScanSubPlan(), ExecSetParamPlan(), expanded_record_set_tuple(), extended_statistics_update(), ExtractReplicaIdentity(), file_acquire_sample_rows(), heap_delete(), heap_insert(), heap_insert_for_repack(), 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 633 of file heaptuple.c.

634{
636
637 Assert(tup);
638
639 /* Currently, no sys attribute ever reads as NULL. */
640 *isnull = false;
641
642 switch (attnum)
643 {
645 /* pass-by-reference datatype */
646 result = PointerGetDatum(&(tup->t_self));
647 break;
650 break;
653 break;
656
657 /*
658 * cmin and cmax are now both aliases for the same field, which
659 * can in fact also be a combo command id. XXX perhaps we should
660 * return the "real" cmin or cmax if possible, that is if we are
661 * inside the originating transaction?
662 */
664 break;
666 result = ObjectIdGetDatum(tup->t_tableOid);
667 break;
668 default:
669 elog(ERROR, "invalid attnum: %d", attnum);
670 result = 0; /* keep compiler quiet */
671 break;
672 }
673 return result;
674}

References Assert, attnum, CommandIdGetDatum(), elog, ERROR, fb(), HeapTupleHeaderGetRawCommandId(), HeapTupleHeaderGetRawXmax(), HeapTupleHeaderGetRawXmin(), MaxCommandIdAttributeNumber, MaxTransactionIdAttributeNumber, MinCommandIdAttributeNumber, MinTransactionIdAttributeNumber, ObjectIdGetDatum(), PointerGetDatum(), result, 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 1118 of file heaptuple.c.

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

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(), copy_index_constraints(), 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 1186 of file heaptuple.c.

1192{
1193 int numberOfAttributes = tupleDesc->natts;
1194 Datum *values;
1195 bool *isnull;
1197 int i;
1198
1199 /*
1200 * allocate and fill values and isnull arrays from the tuple, then replace
1201 * selected columns from the input arrays.
1202 */
1204 isnull = palloc_array(bool, numberOfAttributes);
1205
1206 heap_deform_tuple(tuple, tupleDesc, values, isnull);
1207
1208 for (i = 0; i < nCols; i++)
1209 {
1210 int attnum = replCols[i];
1211
1213 elog(ERROR, "invalid column number %d", attnum);
1214 values[attnum - 1] = replValues[i];
1215 isnull[attnum - 1] = replIsnull[i];
1216 }
1217
1218 /*
1219 * create a new tuple from the values and isnull arrays
1220 */
1222
1223 pfree(values);
1224 pfree(isnull);
1225
1226 /*
1227 * copy the identification info of the old tuple: t_ctid, t_self
1228 */
1229 newTuple->t_data->t_ctid = tuple->t_data->t_ctid;
1230 newTuple->t_self = tuple->t_self;
1231 newTuple->t_tableOid = tuple->t_tableOid;
1232
1233 return newTuple;
1234}

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 1501 of file heaptuple.c.

1502{
1505
1507 result->t_len = len;
1508 ItemPointerSetInvalid(&(result->t_self));
1509 result->t_tableOid = InvalidOid;
1510 result->t_data = (HeapTupleHeader) ((char *) result + HEAPTUPLESIZE);
1511 memcpy((char *) result->t_data + MINIMAL_TUPLE_OFFSET, mtup, mtup->t_len);
1512 memset(result->t_data, 0, offsetof(HeapTupleHeaderData, t_infomask2));
1513 return result;
1514}

References fb(), HEAPTUPLESIZE, InvalidOid, ItemPointerSetInvalid(), len, memcpy(), MINIMAL_TUPLE_OFFSET, palloc(), result, and HeapTupleData::t_len.

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 962 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 1523 of file heaptuple.c.

1524{
1526 char *mem;
1527 uint32 len;
1528
1529 Assert(extra == MAXALIGN(extra));
1531 len = htup->t_len - MINIMAL_TUPLE_OFFSET;
1532 mem = palloc(len + extra);
1533 memset(mem, 0, extra);
1534 result = (MinimalTuple) (mem + extra);
1535 memcpy(result, (char *) htup->t_data + MINIMAL_TUPLE_OFFSET, len);
1536
1537 result->t_len = len;
1538 return result;
1539}

References Assert, fb(), len, MAXALIGN, memcpy(), MINIMAL_TUPLE_OFFSET, palloc(), result, HeapTupleData::t_data, and HeapTupleData::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 uint8 *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 off = att_pointer_alignby(off,
593 cattr->attalignby,
594 attlen,
595 tp + off);
596 off = att_addlength_pointer(off, attlen, tp + off);
597 }
598
599 for (; i < attnum; i++)
600 {
601 int attlen;
602
603 if (att_isnull(i, bp))
604 continue;
605
607 attlen = cattr->attlen;
608 off = att_pointer_alignby(off, cattr->attalignby, attlen,
609 tp + off);
610 off = att_addlength_pointer(off, attlen, tp + off);
611 }
612 }
613
615 off = att_pointer_alignby(off,
616 cattr->attalignby,
617 cattr->attlen,
618 tp + off);
619
620 return fetchatt(cattr, tp + off);
621}

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, HeapTupleHeaderData::t_bits, HeapTupleHeaderData::t_hoff, and TupleDescCompactAttr().

Referenced by fastgetattr().

◆ varsize_any()

size_t varsize_any ( void p)

Definition at line 1546 of file heaptuple.c.

1547{
1548 return VARSIZE_ANY(p);
1549}

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().