865
864
HeapTupleHeader olddata = newtup->t_data;
866
865
HeapTupleHeader new_data;
866
int32 new_header_len;
868
867
int32 new_data_len;
871
* Calculate the new size of the tuple. Header size should not
872
* change, but data size might.
871
* Calculate the new size of the tuple.
873
* Note: we used to assume here that the old tuple's t_hoff must equal
874
* the new_header_len value, but that was incorrect. The old tuple
875
* might have a smaller-than-current natts, if there's been an ALTER
876
* TABLE ADD COLUMN since it was stored; and that would lead to a
877
* different conclusion about the size of the null bitmap, or even
878
* whether there needs to be one at all.
874
new_len = offsetof(HeapTupleHeaderData, t_bits);
880
new_header_len = offsetof(HeapTupleHeaderData, t_bits);
876
new_len += BITMAPLEN(numAttrs);
882
new_header_len += BITMAPLEN(numAttrs);
877
883
if (olddata->t_infomask & HEAP_HASOID)
878
new_len += sizeof(Oid);
879
new_len = MAXALIGN(new_len);
880
Assert(new_len == olddata->t_hoff);
884
new_header_len += sizeof(Oid);
885
new_header_len = MAXALIGN(new_header_len);
881
886
new_data_len = heap_compute_data_size(tupleDesc,
882
887
toast_values, toast_isnull);
883
new_len += new_data_len;
888
new_tuple_len = new_header_len + new_data_len;
886
891
* Allocate and zero the space needed, and fill HeapTupleData fields.
888
result_tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + new_len);
889
result_tuple->t_len = new_len;
893
result_tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + new_tuple_len);
894
result_tuple->t_len = new_tuple_len;
890
895
result_tuple->t_self = newtup->t_self;
891
896
result_tuple->t_tableOid = newtup->t_tableOid;
892
897
new_data = (HeapTupleHeader) ((char *) result_tuple + HEAPTUPLESIZE);
893
898
result_tuple->t_data = new_data;
896
* Put the existing tuple header and the changed values into place
901
* Copy the existing tuple header, but adjust natts and t_hoff.
898
memcpy(new_data, olddata, olddata->t_hoff);
903
memcpy(new_data, olddata, offsetof(HeapTupleHeaderData, t_bits));
904
HeapTupleHeaderSetNatts(new_data, numAttrs);
905
new_data->t_hoff = new_header_len;
906
if (olddata->t_infomask & HEAP_HASOID)
907
HeapTupleHeaderSetOid(new_data, HeapTupleHeaderGetOid(olddata));
909
/* Copy over the data, and fill the null bitmap if needed */
900
910
heap_fill_tuple(tupleDesc,
903
(char *) new_data + olddata->t_hoff,
913
(char *) new_data + new_header_len,
905
915
&(new_data->t_infomask),
906
916
has_nulls ? new_data->t_bits : NULL);
942
* toast_flatten_tuple -
944
* "Flatten" a tuple to contain no out-of-line toasted fields.
945
* (This does not eliminate compressed or short-header datums.)
949
toast_flatten_tuple(HeapTuple tup, TupleDesc tupleDesc)
952
Form_pg_attribute *att = tupleDesc->attrs;
953
int numAttrs = tupleDesc->natts;
955
Datum toast_values[MaxTupleAttributeNumber];
956
bool toast_isnull[MaxTupleAttributeNumber];
957
bool toast_free[MaxTupleAttributeNumber];
960
* Break down the tuple into fields.
962
Assert(numAttrs <= MaxTupleAttributeNumber);
963
heap_deform_tuple(tup, tupleDesc, toast_values, toast_isnull);
965
memset(toast_free, 0, numAttrs * sizeof(bool));
967
for (i = 0; i < numAttrs; i++)
970
* Look at non-null varlena attributes
972
if (!toast_isnull[i] && att[i]->attlen == -1)
974
struct varlena *new_value;
976
new_value = (struct varlena *) DatumGetPointer(toast_values[i]);
977
if (VARATT_IS_EXTERNAL(new_value))
979
new_value = toast_fetch_datum(new_value);
980
toast_values[i] = PointerGetDatum(new_value);
981
toast_free[i] = true;
987
* Form the reconfigured tuple.
989
new_tuple = heap_form_tuple(tupleDesc, toast_values, toast_isnull);
992
* Be sure to copy the tuple's OID and identity fields. We also make a
993
* point of copying visibility info, just in case anybody looks at those
994
* fields in a syscache entry.
996
if (tupleDesc->tdhasoid)
997
HeapTupleSetOid(new_tuple, HeapTupleGetOid(tup));
999
new_tuple->t_self = tup->t_self;
1000
new_tuple->t_tableOid = tup->t_tableOid;
1002
new_tuple->t_data->t_choice = tup->t_data->t_choice;
1003
new_tuple->t_data->t_ctid = tup->t_data->t_ctid;
1004
new_tuple->t_data->t_infomask &= ~HEAP_XACT_MASK;
1005
new_tuple->t_data->t_infomask |=
1006
tup->t_data->t_infomask & HEAP_XACT_MASK;
1007
new_tuple->t_data->t_infomask2 &= ~HEAP2_XACT_MASK;
1008
new_tuple->t_data->t_infomask2 |=
1009
tup->t_data->t_infomask2 & HEAP2_XACT_MASK;
1012
* Free allocated temp values
1014
for (i = 0; i < numAttrs; i++)
1016
pfree(DatumGetPointer(toast_values[i]));
932
1023
* toast_flatten_tuple_attribute -
934
1025
* If a Datum is of composite type, "flatten" it to contain no toasted fields.
1022
* Calculate the new size of the tuple. Header size should not change,
1023
* but data size might.
1114
* Calculate the new size of the tuple.
1116
* This should match the reconstruction code in toast_insert_or_update.
1025
new_len = offsetof(HeapTupleHeaderData, t_bits);
1118
new_header_len = offsetof(HeapTupleHeaderData, t_bits);
1027
new_len += BITMAPLEN(numAttrs);
1120
new_header_len += BITMAPLEN(numAttrs);
1028
1121
if (olddata->t_infomask & HEAP_HASOID)
1029
new_len += sizeof(Oid);
1030
new_len = MAXALIGN(new_len);
1031
Assert(new_len == olddata->t_hoff);
1122
new_header_len += sizeof(Oid);
1123
new_header_len = MAXALIGN(new_header_len);
1032
1124
new_data_len = heap_compute_data_size(tupleDesc,
1033
1125
toast_values, toast_isnull);
1034
new_len += new_data_len;
1126
new_tuple_len = new_header_len + new_data_len;
1036
new_data = (HeapTupleHeader) palloc0(new_len);
1128
new_data = (HeapTupleHeader) palloc0(new_tuple_len);
1039
* Put the tuple header and the changed values into place
1131
* Copy the existing tuple header, but adjust natts and t_hoff.
1041
memcpy(new_data, olddata, olddata->t_hoff);
1043
HeapTupleHeaderSetDatumLength(new_data, new_len);
1133
memcpy(new_data, olddata, offsetof(HeapTupleHeaderData, t_bits));
1134
HeapTupleHeaderSetNatts(new_data, numAttrs);
1135
new_data->t_hoff = new_header_len;
1136
if (olddata->t_infomask & HEAP_HASOID)
1137
HeapTupleHeaderSetOid(new_data, HeapTupleHeaderGetOid(olddata));
1139
/* Reset the datum length field, too */
1140
HeapTupleHeaderSetDatumLength(new_data, new_tuple_len);
1142
/* Copy over the data, and fill the null bitmap if needed */
1045
1143
heap_fill_tuple(tupleDesc,
1048
(char *) new_data + olddata->t_hoff,
1146
(char *) new_data + new_header_len,
1050
1148
&(new_data->t_infomask),
1051
1149
has_nulls ? new_data->t_bits : NULL);