853
852
HeapTupleHeader olddata = newtup->t_data;
854
853
HeapTupleHeader new_data;
854
int32 new_header_len;
856
855
int32 new_data_len;
859
* Calculate the new size of the tuple. Header size should not
860
* change, but data size might.
859
* Calculate the new size of the tuple.
861
* Note: we used to assume here that the old tuple's t_hoff must equal
862
* the new_header_len value, but that was incorrect. The old tuple
863
* might have a smaller-than-current natts, if there's been an ALTER
864
* TABLE ADD COLUMN since it was stored; and that would lead to a
865
* different conclusion about the size of the null bitmap, or even
866
* whether there needs to be one at all.
862
new_len = offsetof(HeapTupleHeaderData, t_bits);
868
new_header_len = offsetof(HeapTupleHeaderData, t_bits);
864
new_len += BITMAPLEN(numAttrs);
870
new_header_len += BITMAPLEN(numAttrs);
865
871
if (olddata->t_infomask & HEAP_HASOID)
866
new_len += sizeof(Oid);
867
new_len = MAXALIGN(new_len);
868
Assert(new_len == olddata->t_hoff);
872
new_header_len += sizeof(Oid);
873
new_header_len = MAXALIGN(new_header_len);
869
874
new_data_len = heap_compute_data_size(tupleDesc,
870
875
toast_values, toast_isnull);
871
new_len += new_data_len;
876
new_tuple_len = new_header_len + new_data_len;
874
879
* Allocate and zero the space needed, and fill HeapTupleData fields.
876
result_tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + new_len);
877
result_tuple->t_len = new_len;
881
result_tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + new_tuple_len);
882
result_tuple->t_len = new_tuple_len;
878
883
result_tuple->t_self = newtup->t_self;
879
884
result_tuple->t_tableOid = newtup->t_tableOid;
880
885
new_data = (HeapTupleHeader) ((char *) result_tuple + HEAPTUPLESIZE);
881
886
result_tuple->t_data = new_data;
884
* Put the existing tuple header and the changed values into place
889
* Copy the existing tuple header, but adjust natts and t_hoff.
886
memcpy(new_data, olddata, olddata->t_hoff);
891
memcpy(new_data, olddata, offsetof(HeapTupleHeaderData, t_bits));
892
HeapTupleHeaderSetNatts(new_data, numAttrs);
893
new_data->t_hoff = new_header_len;
894
if (olddata->t_infomask & HEAP_HASOID)
895
HeapTupleHeaderSetOid(new_data, HeapTupleHeaderGetOid(olddata));
897
/* Copy over the data, and fill the null bitmap if needed */
888
898
heap_fill_tuple(tupleDesc,
891
(char *) new_data + olddata->t_hoff,
901
(char *) new_data + new_header_len,
893
903
&(new_data->t_infomask),
894
904
has_nulls ? new_data->t_bits : NULL);
930
* toast_flatten_tuple -
932
* "Flatten" a tuple to contain no out-of-line toasted fields.
933
* (This does not eliminate compressed or short-header datums.)
937
toast_flatten_tuple(HeapTuple tup, TupleDesc tupleDesc)
940
Form_pg_attribute *att = tupleDesc->attrs;
941
int numAttrs = tupleDesc->natts;
943
Datum toast_values[MaxTupleAttributeNumber];
944
bool toast_isnull[MaxTupleAttributeNumber];
945
bool toast_free[MaxTupleAttributeNumber];
948
* Break down the tuple into fields.
950
Assert(numAttrs <= MaxTupleAttributeNumber);
951
heap_deform_tuple(tup, tupleDesc, toast_values, toast_isnull);
953
memset(toast_free, 0, numAttrs * sizeof(bool));
955
for (i = 0; i < numAttrs; i++)
958
* Look at non-null varlena attributes
960
if (!toast_isnull[i] && att[i]->attlen == -1)
962
struct varlena *new_value;
964
new_value = (struct varlena *) DatumGetPointer(toast_values[i]);
965
if (VARATT_IS_EXTERNAL(new_value))
967
new_value = toast_fetch_datum(new_value);
968
toast_values[i] = PointerGetDatum(new_value);
969
toast_free[i] = true;
975
* Form the reconfigured tuple.
977
new_tuple = heap_form_tuple(tupleDesc, toast_values, toast_isnull);
980
* Be sure to copy the tuple's OID and identity fields. We also make a
981
* point of copying visibility info, just in case anybody looks at those
982
* fields in a syscache entry.
984
if (tupleDesc->tdhasoid)
985
HeapTupleSetOid(new_tuple, HeapTupleGetOid(tup));
987
new_tuple->t_self = tup->t_self;
988
new_tuple->t_tableOid = tup->t_tableOid;
990
new_tuple->t_data->t_choice = tup->t_data->t_choice;
991
new_tuple->t_data->t_ctid = tup->t_data->t_ctid;
992
new_tuple->t_data->t_infomask &= ~HEAP_XACT_MASK;
993
new_tuple->t_data->t_infomask |=
994
tup->t_data->t_infomask & HEAP_XACT_MASK;
995
new_tuple->t_data->t_infomask2 &= ~HEAP2_XACT_MASK;
996
new_tuple->t_data->t_infomask2 |=
997
tup->t_data->t_infomask2 & HEAP2_XACT_MASK;
1000
* Free allocated temp values
1002
for (i = 0; i < numAttrs; i++)
1004
pfree(DatumGetPointer(toast_values[i]));
920
1011
* toast_flatten_tuple_attribute -
922
1013
* If a Datum is of composite type, "flatten" it to contain no toasted fields.
1010
* Calculate the new size of the tuple. Header size should not change,
1011
* but data size might.
1102
* Calculate the new size of the tuple.
1104
* This should match the reconstruction code in toast_insert_or_update.
1013
new_len = offsetof(HeapTupleHeaderData, t_bits);
1106
new_header_len = offsetof(HeapTupleHeaderData, t_bits);
1015
new_len += BITMAPLEN(numAttrs);
1108
new_header_len += BITMAPLEN(numAttrs);
1016
1109
if (olddata->t_infomask & HEAP_HASOID)
1017
new_len += sizeof(Oid);
1018
new_len = MAXALIGN(new_len);
1019
Assert(new_len == olddata->t_hoff);
1110
new_header_len += sizeof(Oid);
1111
new_header_len = MAXALIGN(new_header_len);
1020
1112
new_data_len = heap_compute_data_size(tupleDesc,
1021
1113
toast_values, toast_isnull);
1022
new_len += new_data_len;
1114
new_tuple_len = new_header_len + new_data_len;
1024
new_data = (HeapTupleHeader) palloc0(new_len);
1116
new_data = (HeapTupleHeader) palloc0(new_tuple_len);
1027
* Put the tuple header and the changed values into place
1119
* Copy the existing tuple header, but adjust natts and t_hoff.
1029
memcpy(new_data, olddata, olddata->t_hoff);
1031
HeapTupleHeaderSetDatumLength(new_data, new_len);
1121
memcpy(new_data, olddata, offsetof(HeapTupleHeaderData, t_bits));
1122
HeapTupleHeaderSetNatts(new_data, numAttrs);
1123
new_data->t_hoff = new_header_len;
1124
if (olddata->t_infomask & HEAP_HASOID)
1125
HeapTupleHeaderSetOid(new_data, HeapTupleHeaderGetOid(olddata));
1127
/* Reset the datum length field, too */
1128
HeapTupleHeaderSetDatumLength(new_data, new_tuple_len);
1130
/* Copy over the data, and fill the null bitmap if needed */
1033
1131
heap_fill_tuple(tupleDesc,
1036
(char *) new_data + olddata->t_hoff,
1134
(char *) new_data + new_header_len,
1038
1136
&(new_data->t_infomask),
1039
1137
has_nulls ? new_data->t_bits : NULL);