1 /*-------------------------------------------------------------------------
4 * This file contains heap tuple accessor and mutator routines, as well
5 * as various tuple utilities.
7 * NOTE: there is massive duplication of code in this module to
8 * support both the convention that a null is marked by a bool TRUE,
9 * and the convention that a null is marked by a char 'n'. The latter
10 * convention is deprecated but it'll probably be a long time before
11 * we can get rid of it entirely.
14 * Some notes about varlenas and this code:
16 * Before Postgres 8.3 varlenas always had a 4-byte length header, and
17 * therefore always needed 4-byte alignment (at least). This wasted space
18 * for short varlenas, for example CHAR(1) took 5 bytes and could need up to
19 * 3 additional padding bytes for alignment.
21 * Now, a short varlena (up to 126 data bytes) is reduced to a 1-byte header
22 * and we don't align it. To hide this from datatype-specific functions that
23 * don't want to deal with it, such a datum is considered "toasted" and will
24 * be expanded back to the normal 4-byte-header format by pg_detoast_datum.
25 * (In performance-critical code paths we can use pg_detoast_datum_packed
26 * and the appropriate access macros to avoid that overhead.) Note that this
27 * conversion is performed directly in heap_form_tuple (or heap_formtuple),
28 * without explicitly invoking the toaster.
30 * This change will break any code that assumes it needn't detoast values
31 * that have been put into a tuple but never sent to disk. Hopefully there
32 * are few such places.
34 * Varlenas still have alignment 'i' (or 'd') in pg_type/pg_attribute, since
35 * that's the normal requirement for the untoasted format. But we ignore that
36 * for the 1-byte-header format. This means that the actual start position
37 * of a varlena datum may vary depending on which format it has. To determine
38 * what is stored, we have to require that alignment padding bytes be zero.
39 * (Postgres actually has always zeroed them, but now it's required!) Since
40 * the first byte of a 1-byte-header varlena can never be zero, we can examine
41 * the first byte after the previous datum to tell if it's a pad byte or the
42 * start of a 1-byte-header varlena.
44 * Note that while formerly we could rely on the first varlena column of a
45 * system catalog to be at the offset suggested by the C struct for the
46 * catalog, this is now risky: it's only safe if the preceding field is
47 * word-aligned, so that there will never be any padding.
49 * We don't pack varlenas whose attstorage is 'p', since the data type
50 * isn't expecting to have to detoast values. This is used in particular
51 * by oidvector and int2vector, which are used in the system catalogs
52 * and we'd like to still refer to them via C struct offsets.
55 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
56 * Portions Copyright (c) 1994, Regents of the University of California
62 *-------------------------------------------------------------------------
67 #include "access/heapam.h"
68 #include "access/sysattr.h"
69 #include "access/tuptoaster.h"
70 #include "executor/tuptable.h"
73 /* Does att's datatype allow packing into the 1-byte-header varlena format? */
74 #define ATT_IS_PACKABLE(att) \
75 ((att)->attlen == -1 && (att)->attstorage != 'p')
76 /* Use this if it's already known varlena */
77 #define VARLENA_ATT_IS_PACKABLE(att) \
78 ((att)->attstorage != 'p')
81 /* ----------------------------------------------------------------
82 * misc support routines
83 * ----------------------------------------------------------------
88 * heap_compute_data_size
89 * Determine size of the data area of a tuple to be constructed
92 heap_compute_data_size(TupleDesc tupleDesc
,
98 int numberOfAttributes
= tupleDesc
->natts
;
99 Form_pg_attribute
*att
= tupleDesc
->attrs
;
101 for (i
= 0; i
< numberOfAttributes
; i
++)
110 if (ATT_IS_PACKABLE(att
[i
]) &&
111 VARATT_CAN_MAKE_SHORT(DatumGetPointer(val
)))
114 * we're anticipating converting to a short varlena header, so
115 * adjust length and don't count any alignment
117 data_length
+= VARATT_CONVERTED_SHORT_SIZE(DatumGetPointer(val
));
121 data_length
= att_align_datum(data_length
, att
[i
]->attalign
,
122 att
[i
]->attlen
, val
);
123 data_length
= att_addlength_datum(data_length
, att
[i
]->attlen
,
134 * Determine size of the data area of a tuple to be constructed
136 * OLD API with char 'n'/' ' convention for indicating nulls
140 ComputeDataSize(TupleDesc tupleDesc
,
144 Size data_length
= 0;
146 int numberOfAttributes
= tupleDesc
->natts
;
147 Form_pg_attribute
*att
= tupleDesc
->attrs
;
149 for (i
= 0; i
< numberOfAttributes
; i
++)
158 if (ATT_IS_PACKABLE(att
[i
]) &&
159 VARATT_CAN_MAKE_SHORT(DatumGetPointer(val
)))
162 * we're anticipating converting to a short varlena header, so
163 * adjust length and don't count any alignment
165 data_length
+= VARATT_CONVERTED_SHORT_SIZE(DatumGetPointer(val
));
169 data_length
= att_align_datum(data_length
, att
[i
]->attalign
,
170 att
[i
]->attlen
, val
);
171 data_length
= att_addlength_datum(data_length
, att
[i
]->attlen
,
181 * Load data portion of a tuple from values/isnull arrays
183 * We also fill the null bitmap (if any) and set the infomask bits
184 * that reflect the tuple's data contents.
186 * NOTE: it is now REQUIRED that the caller have pre-zeroed the data area.
189 heap_fill_tuple(TupleDesc tupleDesc
,
190 Datum
*values
, bool *isnull
,
191 char *data
, Size data_size
,
192 uint16
*infomask
, bits8
*bit
)
197 int numberOfAttributes
= tupleDesc
->natts
;
198 Form_pg_attribute
*att
= tupleDesc
->attrs
;
200 #ifdef USE_ASSERT_CHECKING
211 /* just to keep compiler quiet */
216 *infomask
&= ~(HEAP_HASNULL
| HEAP_HASVARWIDTH
| HEAP_HASEXTERNAL
);
218 for (i
= 0; i
< numberOfAttributes
; i
++)
224 if (bitmask
!= HIGHBIT
)
235 *infomask
|= HEAP_HASNULL
;
243 * XXX we use the att_align macros on the pointer value itself, not on
244 * an offset. This is a bit of a hack.
247 if (att
[i
]->attbyval
)
250 data
= (char *) att_align_nominal((long) data
, att
[i
]->attalign
);
251 store_att_byval(data
, values
[i
], att
[i
]->attlen
);
252 data_length
= att
[i
]->attlen
;
254 else if (att
[i
]->attlen
== -1)
257 Pointer val
= DatumGetPointer(values
[i
]);
259 *infomask
|= HEAP_HASVARWIDTH
;
260 if (VARATT_IS_EXTERNAL(val
))
262 *infomask
|= HEAP_HASEXTERNAL
;
263 /* no alignment, since it's short by definition */
264 data_length
= VARSIZE_EXTERNAL(val
);
265 memcpy(data
, val
, data_length
);
267 else if (VARATT_IS_SHORT(val
))
269 /* no alignment for short varlenas */
270 data_length
= VARSIZE_SHORT(val
);
271 memcpy(data
, val
, data_length
);
273 else if (VARLENA_ATT_IS_PACKABLE(att
[i
]) &&
274 VARATT_CAN_MAKE_SHORT(val
))
276 /* convert to short varlena -- no alignment */
277 data_length
= VARATT_CONVERTED_SHORT_SIZE(val
);
278 SET_VARSIZE_SHORT(data
, data_length
);
279 memcpy(data
+ 1, VARDATA(val
), data_length
- 1);
283 /* full 4-byte header varlena */
284 data
= (char *) att_align_nominal((long) data
,
286 data_length
= VARSIZE(val
);
287 memcpy(data
, val
, data_length
);
290 else if (att
[i
]->attlen
== -2)
292 /* cstring ... never needs alignment */
293 *infomask
|= HEAP_HASVARWIDTH
;
294 Assert(att
[i
]->attalign
== 'c');
295 data_length
= strlen(DatumGetCString(values
[i
])) + 1;
296 memcpy(data
, DatumGetPointer(values
[i
]), data_length
);
300 /* fixed-length pass-by-reference */
301 data
= (char *) att_align_nominal((long) data
, att
[i
]->attalign
);
302 Assert(att
[i
]->attlen
> 0);
303 data_length
= att
[i
]->attlen
;
304 memcpy(data
, DatumGetPointer(values
[i
]), data_length
);
310 Assert((data
- start
) == data_size
);
316 * Load data portion of a tuple from values/nulls arrays
318 * OLD API with char 'n'/' ' convention for indicating nulls
322 DataFill(TupleDesc tupleDesc
,
323 Datum
*values
, char *nulls
,
324 char *data
, Size data_size
,
325 uint16
*infomask
, bits8
*bit
)
330 int numberOfAttributes
= tupleDesc
->natts
;
331 Form_pg_attribute
*att
= tupleDesc
->attrs
;
333 #ifdef USE_ASSERT_CHECKING
344 /* just to keep compiler quiet */
349 *infomask
&= ~(HEAP_HASNULL
| HEAP_HASVARWIDTH
| HEAP_HASEXTERNAL
);
351 for (i
= 0; i
< numberOfAttributes
; i
++)
357 if (bitmask
!= HIGHBIT
)
368 *infomask
|= HEAP_HASNULL
;
376 * XXX we use the att_align macros on the pointer value itself, not on
377 * an offset. This is a bit of a hack.
380 if (att
[i
]->attbyval
)
383 data
= (char *) att_align_nominal((long) data
, att
[i
]->attalign
);
384 store_att_byval(data
, values
[i
], att
[i
]->attlen
);
385 data_length
= att
[i
]->attlen
;
387 else if (att
[i
]->attlen
== -1)
390 Pointer val
= DatumGetPointer(values
[i
]);
392 *infomask
|= HEAP_HASVARWIDTH
;
393 if (VARATT_IS_EXTERNAL(val
))
395 *infomask
|= HEAP_HASEXTERNAL
;
396 /* no alignment, since it's short by definition */
397 data_length
= VARSIZE_EXTERNAL(val
);
398 memcpy(data
, val
, data_length
);
400 else if (VARATT_IS_SHORT(val
))
402 /* no alignment for short varlenas */
403 data_length
= VARSIZE_SHORT(val
);
404 memcpy(data
, val
, data_length
);
406 else if (VARLENA_ATT_IS_PACKABLE(att
[i
]) &&
407 VARATT_CAN_MAKE_SHORT(val
))
409 /* convert to short varlena -- no alignment */
410 data_length
= VARATT_CONVERTED_SHORT_SIZE(val
);
411 SET_VARSIZE_SHORT(data
, data_length
);
412 memcpy(data
+ 1, VARDATA(val
), data_length
- 1);
416 /* full 4-byte header varlena */
417 data
= (char *) att_align_nominal((long) data
,
419 data_length
= VARSIZE(val
);
420 memcpy(data
, val
, data_length
);
423 else if (att
[i
]->attlen
== -2)
425 /* cstring ... never needs alignment */
426 *infomask
|= HEAP_HASVARWIDTH
;
427 Assert(att
[i
]->attalign
== 'c');
428 data_length
= strlen(DatumGetCString(values
[i
])) + 1;
429 memcpy(data
, DatumGetPointer(values
[i
]), data_length
);
433 /* fixed-length pass-by-reference */
434 data
= (char *) att_align_nominal((long) data
, att
[i
]->attalign
);
435 Assert(att
[i
]->attlen
> 0);
436 data_length
= att
[i
]->attlen
;
437 memcpy(data
, DatumGetPointer(values
[i
]), data_length
);
443 Assert((data
- start
) == data_size
);
446 /* ----------------------------------------------------------------
447 * heap tuple interface
448 * ----------------------------------------------------------------
452 * heap_attisnull - returns TRUE iff tuple attribute is not present
456 heap_attisnull(HeapTuple tup
, int attnum
)
458 if (attnum
> (int) HeapTupleHeaderGetNatts(tup
->t_data
))
463 if (HeapTupleNoNulls(tup
))
465 return att_isnull(attnum
- 1, tup
->t_data
->t_bits
);
470 case TableOidAttributeNumber
:
471 case SelfItemPointerAttributeNumber
:
472 case ObjectIdAttributeNumber
:
473 case MinTransactionIdAttributeNumber
:
474 case MinCommandIdAttributeNumber
:
475 case MaxTransactionIdAttributeNumber
:
476 case MaxCommandIdAttributeNumber
:
477 /* these are never null */
481 elog(ERROR
, "invalid attnum: %d", attnum
);
490 * This only gets called from fastgetattr() macro, in cases where
491 * we can't use a cacheoffset and the value is not null.
493 * This caches attribute offsets in the attribute descriptor.
495 * An alternative way to speed things up would be to cache offsets
496 * with the tuple, but that seems more difficult unless you take
497 * the storage hit of actually putting those offsets into the
498 * tuple you send to disk. Yuck.
500 * This scheme will be slightly slower than that, but should
501 * perform well for queries which hit large #'s of tuples. After
502 * you cache the offsets once, examining all the other tuples using
503 * the same attribute descriptor will go much quicker. -cim 5/4/91
505 * NOTE: if you need to change this code, see also heap_deform_tuple.
506 * Also see nocache_index_getattr, which is the same code for index
511 nocachegetattr(HeapTuple tuple
,
516 HeapTupleHeader tup
= tuple
->t_data
;
517 Form_pg_attribute
*att
= tupleDesc
->attrs
;
518 char *tp
; /* ptr to data part of tuple */
519 bits8
*bp
= tup
->t_bits
; /* ptr to null bitmap in tuple */
520 bool slow
= false; /* do we have to walk attrs? */
521 int off
; /* current offset within data */
523 (void) isnull
; /* not used */
528 * 1: No nulls and no variable-width attributes.
529 * 2: Has a null or a var-width AFTER att.
530 * 3: Has nulls or var-widths BEFORE att.
535 /* This is handled in the macro */
544 if (HeapTupleNoNulls(tuple
))
547 /* This is handled in the macro */
548 if (att
[attnum
]->attcacheoff
>= 0)
550 return fetchatt(att
[attnum
],
551 (char *) tup
+ tup
->t_hoff
+
552 att
[attnum
]->attcacheoff
);
559 * there's a null somewhere in the tuple
561 * check to see if desired att is null
565 /* This is handled in the macro */
566 if (att_isnull(attnum
, bp
))
575 * Now check to see if any preceding bits are null...
578 int byte
= attnum
>> 3;
579 int finalbit
= attnum
& 0x07;
581 /* check for nulls "before" final bit of last byte */
582 if ((~bp
[byte
]) & ((1 << finalbit
) - 1))
586 /* check for nulls in any "earlier" bytes */
589 for (i
= 0; i
< byte
; i
++)
601 tp
= (char *) tup
+ tup
->t_hoff
;
606 * If we get here, there are no nulls up to and including the target
607 * attribute. If we have a cached offset, we can use it.
609 if (att
[attnum
]->attcacheoff
>= 0)
611 return fetchatt(att
[attnum
],
612 tp
+ att
[attnum
]->attcacheoff
);
616 * Otherwise, check for non-fixed-length attrs up to and including
617 * target. If there aren't any, it's safe to cheaply initialize the
618 * cached offsets for these attrs.
620 if (HeapTupleHasVarWidth(tuple
))
624 for (j
= 0; j
<= attnum
; j
++)
626 if (att
[j
]->attlen
<= 0)
637 int natts
= tupleDesc
->natts
;
641 * If we get here, we have a tuple with no nulls or var-widths up to
642 * and including the target attribute, so we can use the cached offset
643 * ... only we don't have it yet, or we'd not have got here. Since
644 * it's cheap to compute offsets for fixed-width columns, we take the
645 * opportunity to initialize the cached offsets for *all* the leading
646 * fixed-width columns, in hope of avoiding future visits to this
649 att
[0]->attcacheoff
= 0;
651 /* we might have set some offsets in the slow path previously */
652 while (j
< natts
&& att
[j
]->attcacheoff
> 0)
655 off
= att
[j
- 1]->attcacheoff
+ att
[j
- 1]->attlen
;
657 for (; j
< natts
; j
++)
659 if (att
[j
]->attlen
<= 0)
662 off
= att_align_nominal(off
, att
[j
]->attalign
);
664 att
[j
]->attcacheoff
= off
;
666 off
+= att
[j
]->attlen
;
671 off
= att
[attnum
]->attcacheoff
;
675 bool usecache
= true;
679 * Now we know that we have to walk the tuple CAREFULLY. But we still
680 * might be able to cache some offsets for next time.
682 * Note - This loop is a little tricky. For each non-null attribute,
683 * we have to first account for alignment padding before the attr,
684 * then advance over the attr based on its length. Nulls have no
685 * storage and no alignment padding either. We can use/set
686 * attcacheoff until we reach either a null or a var-width attribute.
689 for (i
= 0;; i
++) /* loop exit is at "break" */
691 if (HeapTupleHasNulls(tuple
) && att_isnull(i
, bp
))
694 continue; /* this cannot be the target att */
697 /* If we know the next offset, we can skip the rest */
698 if (usecache
&& att
[i
]->attcacheoff
>= 0)
699 off
= att
[i
]->attcacheoff
;
700 else if (att
[i
]->attlen
== -1)
703 * We can only cache the offset for a varlena attribute if the
704 * offset is already suitably aligned, so that there would be
705 * no pad bytes in any case: then the offset will be valid for
706 * either an aligned or unaligned value.
709 off
== att_align_nominal(off
, att
[i
]->attalign
))
710 att
[i
]->attcacheoff
= off
;
713 off
= att_align_pointer(off
, att
[i
]->attalign
, -1,
720 /* not varlena, so safe to use att_align_nominal */
721 off
= att_align_nominal(off
, att
[i
]->attalign
);
724 att
[i
]->attcacheoff
= off
;
730 off
= att_addlength_pointer(off
, att
[i
]->attlen
, tp
+ off
);
732 if (usecache
&& att
[i
]->attlen
<= 0)
737 return fetchatt(att
[attnum
], tp
+ off
);
743 * Fetch the value of a system attribute for a tuple.
745 * This is a support routine for the heap_getattr macro. The macro
746 * has already determined that the attnum refers to a system attribute.
750 heap_getsysattr(HeapTuple tup
, int attnum
, TupleDesc tupleDesc
, bool *isnull
)
756 /* Currently, no sys attribute ever reads as NULL. */
762 case SelfItemPointerAttributeNumber
:
763 /* pass-by-reference datatype */
764 result
= PointerGetDatum(&(tup
->t_self
));
766 case ObjectIdAttributeNumber
:
767 result
= ObjectIdGetDatum(HeapTupleGetOid(tup
));
769 case MinTransactionIdAttributeNumber
:
770 result
= TransactionIdGetDatum(HeapTupleHeaderGetXmin(tup
->t_data
));
772 case MaxTransactionIdAttributeNumber
:
773 result
= TransactionIdGetDatum(HeapTupleHeaderGetXmax(tup
->t_data
));
775 case MinCommandIdAttributeNumber
:
776 case MaxCommandIdAttributeNumber
:
779 * cmin and cmax are now both aliases for the same field, which
780 * can in fact also be a combo command id. XXX perhaps we should
781 * return the "real" cmin or cmax if possible, that is if we are
782 * inside the originating transaction?
784 result
= CommandIdGetDatum(HeapTupleHeaderGetRawCommandId(tup
->t_data
));
786 case TableOidAttributeNumber
:
787 result
= ObjectIdGetDatum(tup
->t_tableOid
);
790 elog(ERROR
, "invalid attnum: %d", attnum
);
791 result
= 0; /* keep compiler quiet */
800 * returns a copy of an entire tuple
802 * The HeapTuple struct, tuple header, and tuple data are all allocated
803 * as a single palloc() block.
807 heap_copytuple(HeapTuple tuple
)
811 if (!HeapTupleIsValid(tuple
) || tuple
->t_data
== NULL
)
814 newTuple
= (HeapTuple
) palloc(HEAPTUPLESIZE
+ tuple
->t_len
);
815 newTuple
->t_len
= tuple
->t_len
;
816 newTuple
->t_self
= tuple
->t_self
;
817 newTuple
->t_tableOid
= tuple
->t_tableOid
;
818 newTuple
->t_data
= (HeapTupleHeader
) ((char *) newTuple
+ HEAPTUPLESIZE
);
819 memcpy((char *) newTuple
->t_data
, (char *) tuple
->t_data
, tuple
->t_len
);
824 * heap_copytuple_with_tuple
826 * copy a tuple into a caller-supplied HeapTuple management struct
828 * Note that after calling this function, the "dest" HeapTuple will not be
829 * allocated as a single palloc() block (unlike with heap_copytuple()).
833 heap_copytuple_with_tuple(HeapTuple src
, HeapTuple dest
)
835 if (!HeapTupleIsValid(src
) || src
->t_data
== NULL
)
841 dest
->t_len
= src
->t_len
;
842 dest
->t_self
= src
->t_self
;
843 dest
->t_tableOid
= src
->t_tableOid
;
844 dest
->t_data
= (HeapTupleHeader
) palloc(src
->t_len
);
845 memcpy((char *) dest
->t_data
, (char *) src
->t_data
, src
->t_len
);
850 * construct a tuple from the given values[] and isnull[] arrays,
851 * which are of the length indicated by tupleDescriptor->natts
853 * The result is allocated in the current memory context.
856 heap_form_tuple(TupleDesc tupleDescriptor
,
860 HeapTuple tuple
; /* return tuple */
861 HeapTupleHeader td
; /* tuple data */
865 bool hasnull
= false;
866 Form_pg_attribute
*att
= tupleDescriptor
->attrs
;
867 int numberOfAttributes
= tupleDescriptor
->natts
;
870 if (numberOfAttributes
> MaxTupleAttributeNumber
)
872 (errcode(ERRCODE_TOO_MANY_COLUMNS
),
873 errmsg("number of columns (%d) exceeds limit (%d)",
874 numberOfAttributes
, MaxTupleAttributeNumber
)));
877 * Check for nulls and embedded tuples; expand any toasted attributes in
878 * embedded tuples. This preserves the invariant that toasting can only
881 * We can skip calling toast_flatten_tuple_attribute() if the attribute
882 * couldn't possibly be of composite type. All composite datums are
883 * varlena and have alignment 'd'; furthermore they aren't arrays. Also,
884 * if an attribute is already toasted, it must have been sent to disk
885 * already and so cannot contain toasted attributes.
887 for (i
= 0; i
< numberOfAttributes
; i
++)
891 else if (att
[i
]->attlen
== -1 &&
892 att
[i
]->attalign
== 'd' &&
893 att
[i
]->attndims
== 0 &&
894 !VARATT_IS_EXTENDED(DatumGetPointer(values
[i
])))
896 values
[i
] = toast_flatten_tuple_attribute(values
[i
],
903 * Determine total space needed
905 len
= offsetof(HeapTupleHeaderData
, t_bits
);
908 len
+= BITMAPLEN(numberOfAttributes
);
910 if (tupleDescriptor
->tdhasoid
)
913 hoff
= len
= MAXALIGN(len
); /* align user data safely */
915 data_len
= heap_compute_data_size(tupleDescriptor
, values
, isnull
);
920 * Allocate and zero the space needed. Note that the tuple body and
921 * HeapTupleData management structure are allocated in one chunk.
923 tuple
= (HeapTuple
) palloc0(HEAPTUPLESIZE
+ len
);
924 tuple
->t_data
= td
= (HeapTupleHeader
) ((char *) tuple
+ HEAPTUPLESIZE
);
927 * And fill in the information. Note we fill the Datum fields even though
928 * this tuple may never become a Datum.
931 ItemPointerSetInvalid(&(tuple
->t_self
));
932 tuple
->t_tableOid
= InvalidOid
;
934 HeapTupleHeaderSetDatumLength(td
, len
);
935 HeapTupleHeaderSetTypeId(td
, tupleDescriptor
->tdtypeid
);
936 HeapTupleHeaderSetTypMod(td
, tupleDescriptor
->tdtypmod
);
938 HeapTupleHeaderSetNatts(td
, numberOfAttributes
);
941 if (tupleDescriptor
->tdhasoid
) /* else leave infomask = 0 */
942 td
->t_infomask
= HEAP_HASOID
;
944 heap_fill_tuple(tupleDescriptor
,
950 (hasnull
? td
->t_bits
: NULL
));
958 * construct a tuple from the given values[] and nulls[] arrays
960 * Null attributes are indicated by a 'n' in the appropriate byte
961 * of nulls[]. Non-null attributes are indicated by a ' ' (space).
963 * OLD API with char 'n'/' ' convention for indicating nulls
967 heap_formtuple(TupleDesc tupleDescriptor
,
971 HeapTuple tuple
; /* return tuple */
972 HeapTupleHeader td
; /* tuple data */
976 bool hasnull
= false;
977 Form_pg_attribute
*att
= tupleDescriptor
->attrs
;
978 int numberOfAttributes
= tupleDescriptor
->natts
;
981 if (numberOfAttributes
> MaxTupleAttributeNumber
)
983 (errcode(ERRCODE_TOO_MANY_COLUMNS
),
984 errmsg("number of columns (%d) exceeds limit (%d)",
985 numberOfAttributes
, MaxTupleAttributeNumber
)));
988 * Check for nulls and embedded tuples; expand any toasted attributes in
989 * embedded tuples. This preserves the invariant that toasting can only
992 * We can skip calling toast_flatten_tuple_attribute() if the attribute
993 * couldn't possibly be of composite type. All composite datums are
994 * varlena and have alignment 'd'; furthermore they aren't arrays. Also,
995 * if an attribute is already toasted, it must have been sent to disk
996 * already and so cannot contain toasted attributes.
998 for (i
= 0; i
< numberOfAttributes
; i
++)
1000 if (nulls
[i
] != ' ')
1002 else if (att
[i
]->attlen
== -1 &&
1003 att
[i
]->attalign
== 'd' &&
1004 att
[i
]->attndims
== 0 &&
1005 !VARATT_IS_EXTENDED(DatumGetPointer(values
[i
])))
1007 values
[i
] = toast_flatten_tuple_attribute(values
[i
],
1014 * Determine total space needed
1016 len
= offsetof(HeapTupleHeaderData
, t_bits
);
1019 len
+= BITMAPLEN(numberOfAttributes
);
1021 if (tupleDescriptor
->tdhasoid
)
1024 hoff
= len
= MAXALIGN(len
); /* align user data safely */
1026 data_len
= ComputeDataSize(tupleDescriptor
, values
, nulls
);
1031 * Allocate and zero the space needed. Note that the tuple body and
1032 * HeapTupleData management structure are allocated in one chunk.
1034 tuple
= (HeapTuple
) palloc0(HEAPTUPLESIZE
+ len
);
1035 tuple
->t_data
= td
= (HeapTupleHeader
) ((char *) tuple
+ HEAPTUPLESIZE
);
1038 * And fill in the information. Note we fill the Datum fields even though
1039 * this tuple may never become a Datum.
1042 ItemPointerSetInvalid(&(tuple
->t_self
));
1043 tuple
->t_tableOid
= InvalidOid
;
1045 HeapTupleHeaderSetDatumLength(td
, len
);
1046 HeapTupleHeaderSetTypeId(td
, tupleDescriptor
->tdtypeid
);
1047 HeapTupleHeaderSetTypMod(td
, tupleDescriptor
->tdtypmod
);
1049 HeapTupleHeaderSetNatts(td
, numberOfAttributes
);
1052 if (tupleDescriptor
->tdhasoid
) /* else leave infomask = 0 */
1053 td
->t_infomask
= HEAP_HASOID
;
1055 DataFill(tupleDescriptor
,
1061 (hasnull
? td
->t_bits
: NULL
));
1069 * form a new tuple from an old tuple and a set of replacement values.
1071 * The replValues, replIsnull, and doReplace arrays must be of the length
1072 * indicated by tupleDesc->natts. The new tuple is constructed using the data
1073 * from replValues/replIsnull at columns where doReplace is true, and using
1074 * the data from the old tuple at columns where doReplace is false.
1076 * The result is allocated in the current memory context.
1079 heap_modify_tuple(HeapTuple tuple
,
1080 TupleDesc tupleDesc
,
1085 int numberOfAttributes
= tupleDesc
->natts
;
1092 * allocate and fill values and isnull arrays from either the tuple or the
1093 * repl information, as appropriate.
1095 * NOTE: it's debatable whether to use heap_deform_tuple() here or just
1096 * heap_getattr() only the non-replaced colums. The latter could win if
1097 * there are many replaced columns and few non-replaced ones. However,
1098 * heap_deform_tuple costs only O(N) while the heap_getattr way would cost
1099 * O(N^2) if there are many non-replaced columns, so it seems better to
1100 * err on the side of linear cost.
1102 values
= (Datum
*) palloc(numberOfAttributes
* sizeof(Datum
));
1103 isnull
= (bool *) palloc(numberOfAttributes
* sizeof(bool));
1105 heap_deform_tuple(tuple
, tupleDesc
, values
, isnull
);
1107 for (attoff
= 0; attoff
< numberOfAttributes
; attoff
++)
1109 if (doReplace
[attoff
])
1111 values
[attoff
] = replValues
[attoff
];
1112 isnull
[attoff
] = replIsnull
[attoff
];
1117 * create a new tuple from the values and isnull arrays
1119 newTuple
= heap_form_tuple(tupleDesc
, values
, isnull
);
1125 * copy the identification info of the old tuple: t_ctid, t_self, and OID
1128 newTuple
->t_data
->t_ctid
= tuple
->t_data
->t_ctid
;
1129 newTuple
->t_self
= tuple
->t_self
;
1130 newTuple
->t_tableOid
= tuple
->t_tableOid
;
1131 if (tupleDesc
->tdhasoid
)
1132 HeapTupleSetOid(newTuple
, HeapTupleGetOid(tuple
));
1140 * forms a new tuple from an old tuple and a set of replacement values.
1141 * returns a new palloc'ed tuple.
1143 * OLD API with char 'n'/' ' convention for indicating nulls, and
1144 * char 'r'/' ' convention for indicating whether to replace columns.
1148 heap_modifytuple(HeapTuple tuple
,
1149 TupleDesc tupleDesc
,
1154 int numberOfAttributes
= tupleDesc
->natts
;
1161 * allocate and fill values and nulls arrays from either the tuple or the
1162 * repl information, as appropriate.
1164 * NOTE: it's debatable whether to use heap_deformtuple() here or just
1165 * heap_getattr() only the non-replaced colums. The latter could win if
1166 * there are many replaced columns and few non-replaced ones. However,
1167 * heap_deformtuple costs only O(N) while the heap_getattr way would cost
1168 * O(N^2) if there are many non-replaced columns, so it seems better to
1169 * err on the side of linear cost.
1171 values
= (Datum
*) palloc(numberOfAttributes
* sizeof(Datum
));
1172 nulls
= (char *) palloc(numberOfAttributes
* sizeof(char));
1174 heap_deformtuple(tuple
, tupleDesc
, values
, nulls
);
1176 for (attoff
= 0; attoff
< numberOfAttributes
; attoff
++)
1178 if (replActions
[attoff
] == 'r')
1180 values
[attoff
] = replValues
[attoff
];
1181 nulls
[attoff
] = replNulls
[attoff
];
1183 else if (replActions
[attoff
] != ' ')
1184 elog(ERROR
, "unrecognized replace flag: %d",
1185 (int) replActions
[attoff
]);
1189 * create a new tuple from the values and nulls arrays
1191 newTuple
= heap_formtuple(tupleDesc
, values
, nulls
);
1197 * copy the identification info of the old tuple: t_ctid, t_self, and OID
1200 newTuple
->t_data
->t_ctid
= tuple
->t_data
->t_ctid
;
1201 newTuple
->t_self
= tuple
->t_self
;
1202 newTuple
->t_tableOid
= tuple
->t_tableOid
;
1203 if (tupleDesc
->tdhasoid
)
1204 HeapTupleSetOid(newTuple
, HeapTupleGetOid(tuple
));
1211 * Given a tuple, extract data into values/isnull arrays; this is
1212 * the inverse of heap_form_tuple.
1214 * Storage for the values/isnull arrays is provided by the caller;
1215 * it should be sized according to tupleDesc->natts not tuple->t_natts.
1217 * Note that for pass-by-reference datatypes, the pointer placed
1218 * in the Datum will point into the given tuple.
1220 * When all or most of a tuple's fields need to be extracted,
1221 * this routine will be significantly quicker than a loop around
1222 * heap_getattr; the loop will become O(N^2) as soon as any
1223 * noncacheable attribute offsets are involved.
1226 heap_deform_tuple(HeapTuple tuple
, TupleDesc tupleDesc
,
1227 Datum
*values
, bool *isnull
)
1229 HeapTupleHeader tup
= tuple
->t_data
;
1230 bool hasnulls
= HeapTupleHasNulls(tuple
);
1231 Form_pg_attribute
*att
= tupleDesc
->attrs
;
1232 int tdesc_natts
= tupleDesc
->natts
;
1233 int natts
; /* number of atts to extract */
1235 char *tp
; /* ptr to tuple data */
1236 long off
; /* offset in tuple data */
1237 bits8
*bp
= tup
->t_bits
; /* ptr to null bitmap in tuple */
1238 bool slow
= false; /* can we use/set attcacheoff? */
1240 natts
= HeapTupleHeaderGetNatts(tup
);
1243 * In inheritance situations, it is possible that the given tuple actually
1244 * has more fields than the caller is expecting. Don't run off the end of
1245 * the caller's arrays.
1247 natts
= Min(natts
, tdesc_natts
);
1249 tp
= (char *) tup
+ tup
->t_hoff
;
1253 for (attnum
= 0; attnum
< natts
; attnum
++)
1255 Form_pg_attribute thisatt
= att
[attnum
];
1257 if (hasnulls
&& att_isnull(attnum
, bp
))
1259 values
[attnum
] = (Datum
) 0;
1260 isnull
[attnum
] = true;
1261 slow
= true; /* can't use attcacheoff anymore */
1265 isnull
[attnum
] = false;
1267 if (!slow
&& thisatt
->attcacheoff
>= 0)
1268 off
= thisatt
->attcacheoff
;
1269 else if (thisatt
->attlen
== -1)
1272 * We can only cache the offset for a varlena attribute if the
1273 * offset is already suitably aligned, so that there would be no
1274 * pad bytes in any case: then the offset will be valid for either
1275 * an aligned or unaligned value.
1278 off
== att_align_nominal(off
, thisatt
->attalign
))
1279 thisatt
->attcacheoff
= off
;
1282 off
= att_align_pointer(off
, thisatt
->attalign
, -1,
1289 /* not varlena, so safe to use att_align_nominal */
1290 off
= att_align_nominal(off
, thisatt
->attalign
);
1293 thisatt
->attcacheoff
= off
;
1296 values
[attnum
] = fetchatt(thisatt
, tp
+ off
);
1298 off
= att_addlength_pointer(off
, thisatt
->attlen
, tp
+ off
);
1300 if (thisatt
->attlen
<= 0)
1301 slow
= true; /* can't use attcacheoff anymore */
1305 * If tuple doesn't have all the atts indicated by tupleDesc, read the
1308 for (; attnum
< tdesc_natts
; attnum
++)
1310 values
[attnum
] = (Datum
) 0;
1311 isnull
[attnum
] = true;
1318 * Given a tuple, extract data into values/nulls arrays; this is
1319 * the inverse of heap_formtuple.
1321 * Storage for the values/nulls arrays is provided by the caller;
1322 * it should be sized according to tupleDesc->natts not tuple->t_natts.
1324 * Note that for pass-by-reference datatypes, the pointer placed
1325 * in the Datum will point into the given tuple.
1327 * When all or most of a tuple's fields need to be extracted,
1328 * this routine will be significantly quicker than a loop around
1329 * heap_getattr; the loop will become O(N^2) as soon as any
1330 * noncacheable attribute offsets are involved.
1332 * OLD API with char 'n'/' ' convention for indicating nulls
1336 heap_deformtuple(HeapTuple tuple
,
1337 TupleDesc tupleDesc
,
1341 HeapTupleHeader tup
= tuple
->t_data
;
1342 bool hasnulls
= HeapTupleHasNulls(tuple
);
1343 Form_pg_attribute
*att
= tupleDesc
->attrs
;
1344 int tdesc_natts
= tupleDesc
->natts
;
1345 int natts
; /* number of atts to extract */
1347 char *tp
; /* ptr to tuple data */
1348 long off
; /* offset in tuple data */
1349 bits8
*bp
= tup
->t_bits
; /* ptr to null bitmap in tuple */
1350 bool slow
= false; /* can we use/set attcacheoff? */
1352 natts
= HeapTupleHeaderGetNatts(tup
);
1355 * In inheritance situations, it is possible that the given tuple actually
1356 * has more fields than the caller is expecting. Don't run off the end of
1357 * the caller's arrays.
1359 natts
= Min(natts
, tdesc_natts
);
1361 tp
= (char *) tup
+ tup
->t_hoff
;
1365 for (attnum
= 0; attnum
< natts
; attnum
++)
1367 Form_pg_attribute thisatt
= att
[attnum
];
1369 if (hasnulls
&& att_isnull(attnum
, bp
))
1371 values
[attnum
] = (Datum
) 0;
1372 nulls
[attnum
] = 'n';
1373 slow
= true; /* can't use attcacheoff anymore */
1377 nulls
[attnum
] = ' ';
1379 if (!slow
&& thisatt
->attcacheoff
>= 0)
1380 off
= thisatt
->attcacheoff
;
1381 else if (thisatt
->attlen
== -1)
1384 * We can only cache the offset for a varlena attribute if the
1385 * offset is already suitably aligned, so that there would be no
1386 * pad bytes in any case: then the offset will be valid for either
1387 * an aligned or unaligned value.
1390 off
== att_align_nominal(off
, thisatt
->attalign
))
1391 thisatt
->attcacheoff
= off
;
1394 off
= att_align_pointer(off
, thisatt
->attalign
, -1,
1401 /* not varlena, so safe to use att_align_nominal */
1402 off
= att_align_nominal(off
, thisatt
->attalign
);
1405 thisatt
->attcacheoff
= off
;
1408 values
[attnum
] = fetchatt(thisatt
, tp
+ off
);
1410 off
= att_addlength_pointer(off
, thisatt
->attlen
, tp
+ off
);
1412 if (thisatt
->attlen
<= 0)
1413 slow
= true; /* can't use attcacheoff anymore */
1417 * If tuple doesn't have all the atts indicated by tupleDesc, read the
1420 for (; attnum
< tdesc_natts
; attnum
++)
1422 values
[attnum
] = (Datum
) 0;
1423 nulls
[attnum
] = 'n';
1429 * Given a TupleTableSlot, extract data from the slot's physical tuple
1430 * into its Datum/isnull arrays. Data is extracted up through the
1431 * natts'th column (caller must ensure this is a legal column number).
1433 * This is essentially an incremental version of heap_deform_tuple:
1434 * on each call we extract attributes up to the one needed, without
1435 * re-computing information about previously extracted attributes.
1436 * slot->tts_nvalid is the number of attributes already extracted.
1439 slot_deform_tuple(TupleTableSlot
*slot
, int natts
)
1441 HeapTuple tuple
= slot
->tts_tuple
;
1442 TupleDesc tupleDesc
= slot
->tts_tupleDescriptor
;
1443 Datum
*values
= slot
->tts_values
;
1444 bool *isnull
= slot
->tts_isnull
;
1445 HeapTupleHeader tup
= tuple
->t_data
;
1446 bool hasnulls
= HeapTupleHasNulls(tuple
);
1447 Form_pg_attribute
*att
= tupleDesc
->attrs
;
1449 char *tp
; /* ptr to tuple data */
1450 long off
; /* offset in tuple data */
1451 bits8
*bp
= tup
->t_bits
; /* ptr to null bitmap in tuple */
1452 bool slow
; /* can we use/set attcacheoff? */
1455 * Check whether the first call for this tuple, and initialize or restore
1458 attnum
= slot
->tts_nvalid
;
1461 /* Start from the first attribute */
1467 /* Restore state from previous execution */
1468 off
= slot
->tts_off
;
1469 slow
= slot
->tts_slow
;
1472 tp
= (char *) tup
+ tup
->t_hoff
;
1474 for (; attnum
< natts
; attnum
++)
1476 Form_pg_attribute thisatt
= att
[attnum
];
1478 if (hasnulls
&& att_isnull(attnum
, bp
))
1480 values
[attnum
] = (Datum
) 0;
1481 isnull
[attnum
] = true;
1482 slow
= true; /* can't use attcacheoff anymore */
1486 isnull
[attnum
] = false;
1488 if (!slow
&& thisatt
->attcacheoff
>= 0)
1489 off
= thisatt
->attcacheoff
;
1490 else if (thisatt
->attlen
== -1)
1493 * We can only cache the offset for a varlena attribute if the
1494 * offset is already suitably aligned, so that there would be no
1495 * pad bytes in any case: then the offset will be valid for either
1496 * an aligned or unaligned value.
1499 off
== att_align_nominal(off
, thisatt
->attalign
))
1500 thisatt
->attcacheoff
= off
;
1503 off
= att_align_pointer(off
, thisatt
->attalign
, -1,
1510 /* not varlena, so safe to use att_align_nominal */
1511 off
= att_align_nominal(off
, thisatt
->attalign
);
1514 thisatt
->attcacheoff
= off
;
1517 values
[attnum
] = fetchatt(thisatt
, tp
+ off
);
1519 off
= att_addlength_pointer(off
, thisatt
->attlen
, tp
+ off
);
1521 if (thisatt
->attlen
<= 0)
1522 slow
= true; /* can't use attcacheoff anymore */
1526 * Save state for next execution
1528 slot
->tts_nvalid
= attnum
;
1529 slot
->tts_off
= off
;
1530 slot
->tts_slow
= slow
;
1535 * This function fetches an attribute of the slot's current tuple.
1536 * It is functionally equivalent to heap_getattr, but fetches of
1537 * multiple attributes of the same tuple will be optimized better,
1538 * because we avoid O(N^2) behavior from multiple calls of
1539 * nocachegetattr(), even when attcacheoff isn't usable.
1541 * A difference from raw heap_getattr is that attnums beyond the
1542 * slot's tupdesc's last attribute will be considered NULL even
1543 * when the physical tuple is longer than the tupdesc.
1546 slot_getattr(TupleTableSlot
*slot
, int attnum
, bool *isnull
)
1548 HeapTuple tuple
= slot
->tts_tuple
;
1549 TupleDesc tupleDesc
= slot
->tts_tupleDescriptor
;
1550 HeapTupleHeader tup
;
1553 * system attributes are handled by heap_getsysattr
1557 if (tuple
== NULL
) /* internal error */
1558 elog(ERROR
, "cannot extract system attribute from virtual tuple");
1559 if (slot
->tts_mintuple
) /* internal error */
1560 elog(ERROR
, "cannot extract system attribute from minimal tuple");
1561 return heap_getsysattr(tuple
, attnum
, tupleDesc
, isnull
);
1565 * fast path if desired attribute already cached
1567 if (attnum
<= slot
->tts_nvalid
)
1569 *isnull
= slot
->tts_isnull
[attnum
- 1];
1570 return slot
->tts_values
[attnum
- 1];
1574 * return NULL if attnum is out of range according to the tupdesc
1576 if (attnum
> tupleDesc
->natts
)
1583 * otherwise we had better have a physical tuple (tts_nvalid should equal
1584 * natts in all virtual-tuple cases)
1586 if (tuple
== NULL
) /* internal error */
1587 elog(ERROR
, "cannot extract attribute from empty tuple slot");
1590 * return NULL if attnum is out of range according to the tuple
1592 * (We have to check this separately because of various inheritance and
1593 * table-alteration scenarios: the tuple could be either longer or shorter
1594 * than the tupdesc.)
1596 tup
= tuple
->t_data
;
1597 if (attnum
> HeapTupleHeaderGetNatts(tup
))
1604 * check if target attribute is null: no point in groveling through tuple
1606 if (HeapTupleHasNulls(tuple
) && att_isnull(attnum
- 1, tup
->t_bits
))
1613 * If the attribute's column has been dropped, we force a NULL result.
1614 * This case should not happen in normal use, but it could happen if we
1615 * are executing a plan cached before the column was dropped.
1617 if (tupleDesc
->attrs
[attnum
- 1]->attisdropped
)
1624 * Extract the attribute, along with any preceding attributes.
1626 slot_deform_tuple(slot
, attnum
);
1629 * The result is acquired from tts_values array.
1631 *isnull
= slot
->tts_isnull
[attnum
- 1];
1632 return slot
->tts_values
[attnum
- 1];
1637 * This function forces all the entries of the slot's Datum/isnull
1638 * arrays to be valid. The caller may then extract data directly
1639 * from those arrays instead of using slot_getattr.
1642 slot_getallattrs(TupleTableSlot
*slot
)
1644 int tdesc_natts
= slot
->tts_tupleDescriptor
->natts
;
1648 /* Quick out if we have 'em all already */
1649 if (slot
->tts_nvalid
== tdesc_natts
)
1653 * otherwise we had better have a physical tuple (tts_nvalid should equal
1654 * natts in all virtual-tuple cases)
1656 tuple
= slot
->tts_tuple
;
1657 if (tuple
== NULL
) /* internal error */
1658 elog(ERROR
, "cannot extract attribute from empty tuple slot");
1661 * load up any slots available from physical tuple
1663 attnum
= HeapTupleHeaderGetNatts(tuple
->t_data
);
1664 attnum
= Min(attnum
, tdesc_natts
);
1666 slot_deform_tuple(slot
, attnum
);
1669 * If tuple doesn't have all the atts indicated by tupleDesc, read the
1672 for (; attnum
< tdesc_natts
; attnum
++)
1674 slot
->tts_values
[attnum
] = (Datum
) 0;
1675 slot
->tts_isnull
[attnum
] = true;
1677 slot
->tts_nvalid
= tdesc_natts
;
1682 * This function forces the entries of the slot's Datum/isnull
1683 * arrays to be valid at least up through the attnum'th entry.
1686 slot_getsomeattrs(TupleTableSlot
*slot
, int attnum
)
1691 /* Quick out if we have 'em all already */
1692 if (slot
->tts_nvalid
>= attnum
)
1695 /* Check for caller error */
1696 if (attnum
<= 0 || attnum
> slot
->tts_tupleDescriptor
->natts
)
1697 elog(ERROR
, "invalid attribute number %d", attnum
);
1700 * otherwise we had better have a physical tuple (tts_nvalid should equal
1701 * natts in all virtual-tuple cases)
1703 tuple
= slot
->tts_tuple
;
1704 if (tuple
== NULL
) /* internal error */
1705 elog(ERROR
, "cannot extract attribute from empty tuple slot");
1708 * load up any slots available from physical tuple
1710 attno
= HeapTupleHeaderGetNatts(tuple
->t_data
);
1711 attno
= Min(attno
, attnum
);
1713 slot_deform_tuple(slot
, attno
);
1716 * If tuple doesn't have all the atts indicated by tupleDesc, read the
1719 for (; attno
< attnum
; attno
++)
1721 slot
->tts_values
[attno
] = (Datum
) 0;
1722 slot
->tts_isnull
[attno
] = true;
1724 slot
->tts_nvalid
= attnum
;
1729 * Detect whether an attribute of the slot is null, without
1730 * actually fetching it.
1733 slot_attisnull(TupleTableSlot
*slot
, int attnum
)
1735 HeapTuple tuple
= slot
->tts_tuple
;
1736 TupleDesc tupleDesc
= slot
->tts_tupleDescriptor
;
1739 * system attributes are handled by heap_attisnull
1743 if (tuple
== NULL
) /* internal error */
1744 elog(ERROR
, "cannot extract system attribute from virtual tuple");
1745 if (slot
->tts_mintuple
) /* internal error */
1746 elog(ERROR
, "cannot extract system attribute from minimal tuple");
1747 return heap_attisnull(tuple
, attnum
);
1751 * fast path if desired attribute already cached
1753 if (attnum
<= slot
->tts_nvalid
)
1754 return slot
->tts_isnull
[attnum
- 1];
1757 * return NULL if attnum is out of range according to the tupdesc
1759 if (attnum
> tupleDesc
->natts
)
1763 * otherwise we had better have a physical tuple (tts_nvalid should equal
1764 * natts in all virtual-tuple cases)
1766 if (tuple
== NULL
) /* internal error */
1767 elog(ERROR
, "cannot extract attribute from empty tuple slot");
1769 /* and let the tuple tell it */
1770 return heap_attisnull(tuple
, attnum
);
1777 heap_freetuple(HeapTuple htup
)
1784 * heap_form_minimal_tuple
1785 * construct a MinimalTuple from the given values[] and isnull[] arrays,
1786 * which are of the length indicated by tupleDescriptor->natts
1788 * This is exactly like heap_form_tuple() except that the result is a
1789 * "minimal" tuple lacking a HeapTupleData header as well as room for system
1792 * The result is allocated in the current memory context.
1795 heap_form_minimal_tuple(TupleDesc tupleDescriptor
,
1799 MinimalTuple tuple
; /* return tuple */
1803 bool hasnull
= false;
1804 Form_pg_attribute
*att
= tupleDescriptor
->attrs
;
1805 int numberOfAttributes
= tupleDescriptor
->natts
;
1808 if (numberOfAttributes
> MaxTupleAttributeNumber
)
1810 (errcode(ERRCODE_TOO_MANY_COLUMNS
),
1811 errmsg("number of columns (%d) exceeds limit (%d)",
1812 numberOfAttributes
, MaxTupleAttributeNumber
)));
1815 * Check for nulls and embedded tuples; expand any toasted attributes in
1816 * embedded tuples. This preserves the invariant that toasting can only
1817 * go one level deep.
1819 * We can skip calling toast_flatten_tuple_attribute() if the attribute
1820 * couldn't possibly be of composite type. All composite datums are
1821 * varlena and have alignment 'd'; furthermore they aren't arrays. Also,
1822 * if an attribute is already toasted, it must have been sent to disk
1823 * already and so cannot contain toasted attributes.
1825 for (i
= 0; i
< numberOfAttributes
; i
++)
1829 else if (att
[i
]->attlen
== -1 &&
1830 att
[i
]->attalign
== 'd' &&
1831 att
[i
]->attndims
== 0 &&
1832 !VARATT_IS_EXTENDED(values
[i
]))
1834 values
[i
] = toast_flatten_tuple_attribute(values
[i
],
1841 * Determine total space needed
1843 len
= offsetof(MinimalTupleData
, t_bits
);
1846 len
+= BITMAPLEN(numberOfAttributes
);
1848 if (tupleDescriptor
->tdhasoid
)
1851 hoff
= len
= MAXALIGN(len
); /* align user data safely */
1853 data_len
= heap_compute_data_size(tupleDescriptor
, values
, isnull
);
1858 * Allocate and zero the space needed.
1860 tuple
= (MinimalTuple
) palloc0(len
);
1863 * And fill in the information.
1866 HeapTupleHeaderSetNatts(tuple
, numberOfAttributes
);
1867 tuple
->t_hoff
= hoff
+ MINIMAL_TUPLE_OFFSET
;
1869 if (tupleDescriptor
->tdhasoid
) /* else leave infomask = 0 */
1870 tuple
->t_infomask
= HEAP_HASOID
;
1872 heap_fill_tuple(tupleDescriptor
,
1875 (char *) tuple
+ hoff
,
1878 (hasnull
? tuple
->t_bits
: NULL
));
1884 * heap_free_minimal_tuple
1887 heap_free_minimal_tuple(MinimalTuple mtup
)
1893 * heap_copy_minimal_tuple
1894 * copy a MinimalTuple
1896 * The result is allocated in the current memory context.
1899 heap_copy_minimal_tuple(MinimalTuple mtup
)
1901 MinimalTuple result
;
1903 result
= (MinimalTuple
) palloc(mtup
->t_len
);
1904 memcpy(result
, mtup
, mtup
->t_len
);
1909 * heap_tuple_from_minimal_tuple
1910 * create a HeapTuple by copying from a MinimalTuple;
1911 * system columns are filled with zeroes
1913 * The result is allocated in the current memory context.
1914 * The HeapTuple struct, tuple header, and tuple data are all allocated
1915 * as a single palloc() block.
1918 heap_tuple_from_minimal_tuple(MinimalTuple mtup
)
1921 uint32 len
= mtup
->t_len
+ MINIMAL_TUPLE_OFFSET
;
1923 result
= (HeapTuple
) palloc(HEAPTUPLESIZE
+ len
);
1924 result
->t_len
= len
;
1925 ItemPointerSetInvalid(&(result
->t_self
));
1926 result
->t_tableOid
= InvalidOid
;
1927 result
->t_data
= (HeapTupleHeader
) ((char *) result
+ HEAPTUPLESIZE
);
1928 memcpy((char *) result
->t_data
+ MINIMAL_TUPLE_OFFSET
, mtup
, mtup
->t_len
);
1929 memset(result
->t_data
, 0, offsetof(HeapTupleHeaderData
, t_infomask2
));
1934 * minimal_tuple_from_heap_tuple
1935 * create a MinimalTuple by copying from a HeapTuple
1937 * The result is allocated in the current memory context.
1940 minimal_tuple_from_heap_tuple(HeapTuple htup
)
1942 MinimalTuple result
;
1945 Assert(htup
->t_len
> MINIMAL_TUPLE_OFFSET
);
1946 len
= htup
->t_len
- MINIMAL_TUPLE_OFFSET
;
1947 result
= (MinimalTuple
) palloc(len
);
1948 memcpy(result
, (char *) htup
->t_data
+ MINIMAL_TUPLE_OFFSET
, len
);
1949 result
->t_len
= len
;
1957 * This routine forms a HeapTuple by copying the given structure (tuple
1958 * data) and adding a generic header. Note that the tuple data is
1959 * presumed to contain no null fields and no varlena fields.
1961 * This routine is really only useful for certain system tables that are
1962 * known to be fixed-width and null-free. Currently it is only used for
1963 * pg_attribute tuples.
1967 heap_addheader(int natts
, /* max domain index */
1968 bool withoid
, /* reserve space for oid */
1969 Size structlen
, /* its length */
1970 void *structure
) /* pointer to the struct */
1977 AssertArg(natts
> 0);
1979 /* header needs no null bitmap */
1980 hoff
= offsetof(HeapTupleHeaderData
, t_bits
);
1982 hoff
+= sizeof(Oid
);
1983 hoff
= MAXALIGN(hoff
);
1984 len
= hoff
+ structlen
;
1986 tuple
= (HeapTuple
) palloc0(HEAPTUPLESIZE
+ len
);
1987 tuple
->t_data
= td
= (HeapTupleHeader
) ((char *) tuple
+ HEAPTUPLESIZE
);
1990 ItemPointerSetInvalid(&(tuple
->t_self
));
1991 tuple
->t_tableOid
= InvalidOid
;
1993 /* we don't bother to fill the Datum fields */
1995 HeapTupleHeaderSetNatts(td
, natts
);
1998 if (withoid
) /* else leave infomask = 0 */
1999 td
->t_infomask
= HEAP_HASOID
;
2001 memcpy((char *) td
+ hoff
, structure
, structlen
);