Use FLEXIBLE_ARRAY_MEMBER for HeapTupleHeaderData.t_bits[].

This requires changing quite a few places that were depending on
sizeof(HeapTupleHeaderData), but it seems for the best.

Michael Paquier, some adjustments by me
This commit is contained in:
Tom Lane 2015-02-21 15:13:06 -05:00
parent 3d9b6f31ee
commit e1a11d9311
19 changed files with 102 additions and 99 deletions

View File

@ -932,7 +932,7 @@ estimate_size(PlannerInfo *root, RelOptInfo *baserel,
int tuple_width; int tuple_width;
tuple_width = MAXALIGN(baserel->width) + tuple_width = MAXALIGN(baserel->width) +
MAXALIGN(sizeof(HeapTupleHeaderData)); MAXALIGN(SizeofHeapTupleHeader);
ntuples = clamp_row_est((double) stat_buf.st_size / ntuples = clamp_row_est((double) stat_buf.st_size /
(double) tuple_width); (double) tuple_width);
} }

View File

@ -149,7 +149,7 @@ heap_page_items(PG_FUNCTION_ARGS)
* many other ways, but at least we won't crash. * many other ways, but at least we won't crash.
*/ */
if (ItemIdHasStorage(id) && if (ItemIdHasStorage(id) &&
lp_len >= sizeof(HeapTupleHeader) && lp_len >= MinHeapTupleSize &&
lp_offset == MAXALIGN(lp_offset) && lp_offset == MAXALIGN(lp_offset) &&
lp_offset + lp_len <= raw_page_size) lp_offset + lp_len <= raw_page_size)
{ {
@ -169,18 +169,19 @@ heap_page_items(PG_FUNCTION_ARGS)
values[10] = UInt8GetDatum(tuphdr->t_hoff); values[10] = UInt8GetDatum(tuphdr->t_hoff);
/* /*
* We already checked that the item as is completely within the * We already checked that the item is completely within the raw
* raw page passed to us, with the length given in the line * page passed to us, with the length given in the line pointer.
* pointer.. Let's check that t_hoff doesn't point over lp_len, * Let's check that t_hoff doesn't point over lp_len, before using
* before using it to access t_bits and oid. * it to access t_bits and oid.
*/ */
if (tuphdr->t_hoff >= sizeof(HeapTupleHeader) && if (tuphdr->t_hoff >= SizeofHeapTupleHeader &&
tuphdr->t_hoff <= lp_len) tuphdr->t_hoff <= lp_len &&
tuphdr->t_hoff == MAXALIGN(tuphdr->t_hoff))
{ {
if (tuphdr->t_infomask & HEAP_HASNULL) if (tuphdr->t_infomask & HEAP_HASNULL)
{ {
bits_len = tuphdr->t_hoff - bits_len = tuphdr->t_hoff -
(((char *) tuphdr->t_bits) -((char *) tuphdr)); offsetof(HeapTupleHeaderData, t_bits);
values[11] = CStringGetTextDatum( values[11] = CStringGetTextDatum(
bits_to_text(tuphdr->t_bits, bits_len * 8)); bits_to_text(tuphdr->t_bits, bits_len * 8));

View File

@ -519,7 +519,7 @@ postgresGetForeignRelSize(PlannerInfo *root,
{ {
baserel->pages = 10; baserel->pages = 10;
baserel->tuples = baserel->tuples =
(10 * BLCKSZ) / (baserel->width + sizeof(HeapTupleHeaderData)); (10 * BLCKSZ) / (baserel->width + MAXALIGN(SizeofHeapTupleHeader));
} }
/* Estimate baserel size as best we can with local statistics. */ /* Estimate baserel size as best we can with local statistics. */

View File

@ -1434,7 +1434,7 @@ heap_form_minimal_tuple(TupleDesc tupleDescriptor,
/* /*
* Determine total space needed * Determine total space needed
*/ */
len = offsetof(MinimalTupleData, t_bits); len = SizeofMinimalTupleHeader;
if (hasnull) if (hasnull)
len += BITMAPLEN(numberOfAttributes); len += BITMAPLEN(numberOfAttributes);

View File

@ -2186,8 +2186,8 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
XLogRegisterBufData(0, (char *) &xlhdr, SizeOfHeapHeader); XLogRegisterBufData(0, (char *) &xlhdr, SizeOfHeapHeader);
/* PG73FORMAT: write bitmap [+ padding] [+ oid] + data */ /* PG73FORMAT: write bitmap [+ padding] [+ oid] + data */
XLogRegisterBufData(0, XLogRegisterBufData(0,
(char *) heaptup->t_data + offsetof(HeapTupleHeaderData, t_bits), (char *) heaptup->t_data + SizeofHeapTupleHeader,
heaptup->t_len - offsetof(HeapTupleHeaderData, t_bits)); heaptup->t_len - SizeofHeapTupleHeader);
recptr = XLogInsert(RM_HEAP_ID, info); recptr = XLogInsert(RM_HEAP_ID, info);
@ -2460,9 +2460,9 @@ heap_multi_insert(Relation relation, HeapTuple *tuples, int ntuples,
tuphdr->t_hoff = heaptup->t_data->t_hoff; tuphdr->t_hoff = heaptup->t_data->t_hoff;
/* write bitmap [+ padding] [+ oid] + data */ /* write bitmap [+ padding] [+ oid] + data */
datalen = heaptup->t_len - offsetof(HeapTupleHeaderData, t_bits); datalen = heaptup->t_len - SizeofHeapTupleHeader;
memcpy(scratchptr, memcpy(scratchptr,
(char *) heaptup->t_data + offsetof(HeapTupleHeaderData, t_bits), (char *) heaptup->t_data + SizeofHeapTupleHeader,
datalen); datalen);
tuphdr->datalen = datalen; tuphdr->datalen = datalen;
scratchptr += datalen; scratchptr += datalen;
@ -2904,9 +2904,9 @@ l1:
XLogRegisterData((char *) &xlhdr, SizeOfHeapHeader); XLogRegisterData((char *) &xlhdr, SizeOfHeapHeader);
XLogRegisterData((char *) old_key_tuple->t_data XLogRegisterData((char *) old_key_tuple->t_data
+ offsetof(HeapTupleHeaderData, t_bits), + SizeofHeapTupleHeader,
old_key_tuple->t_len old_key_tuple->t_len
- offsetof(HeapTupleHeaderData, t_bits)); - SizeofHeapTupleHeader);
} }
recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_DELETE); recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_DELETE);
@ -6732,7 +6732,7 @@ log_heap_update(Relation reln, Buffer oldbuf,
xlhdr.t_infomask2 = newtup->t_data->t_infomask2; xlhdr.t_infomask2 = newtup->t_data->t_infomask2;
xlhdr.t_infomask = newtup->t_data->t_infomask; xlhdr.t_infomask = newtup->t_data->t_infomask;
xlhdr.t_hoff = newtup->t_data->t_hoff; xlhdr.t_hoff = newtup->t_data->t_hoff;
Assert(offsetof(HeapTupleHeaderData, t_bits) + prefixlen + suffixlen <= newtup->t_len); Assert(SizeofHeapTupleHeader + prefixlen + suffixlen <= newtup->t_len);
/* /*
* PG73FORMAT: write bitmap [+ padding] [+ oid] + data * PG73FORMAT: write bitmap [+ padding] [+ oid] + data
@ -6743,8 +6743,8 @@ log_heap_update(Relation reln, Buffer oldbuf,
if (prefixlen == 0) if (prefixlen == 0)
{ {
XLogRegisterBufData(0, XLogRegisterBufData(0,
((char *) newtup->t_data) + offsetof(HeapTupleHeaderData, t_bits), ((char *) newtup->t_data) + SizeofHeapTupleHeader,
newtup->t_len - offsetof(HeapTupleHeaderData, t_bits) -suffixlen); newtup->t_len - SizeofHeapTupleHeader - suffixlen);
} }
else else
{ {
@ -6753,11 +6753,11 @@ log_heap_update(Relation reln, Buffer oldbuf,
* two separate rdata entries. * two separate rdata entries.
*/ */
/* bitmap [+ padding] [+ oid] */ /* bitmap [+ padding] [+ oid] */
if (newtup->t_data->t_hoff - offsetof(HeapTupleHeaderData, t_bits) >0) if (newtup->t_data->t_hoff - SizeofHeapTupleHeader > 0)
{ {
XLogRegisterBufData(0, XLogRegisterBufData(0,
((char *) newtup->t_data) + offsetof(HeapTupleHeaderData, t_bits), ((char *) newtup->t_data) + SizeofHeapTupleHeader,
newtup->t_data->t_hoff - offsetof(HeapTupleHeaderData, t_bits)); newtup->t_data->t_hoff - SizeofHeapTupleHeader);
} }
/* data after common prefix */ /* data after common prefix */
@ -6777,8 +6777,8 @@ log_heap_update(Relation reln, Buffer oldbuf,
XLogRegisterData((char *) &xlhdr_idx, SizeOfHeapHeader); XLogRegisterData((char *) &xlhdr_idx, SizeOfHeapHeader);
/* PG73FORMAT: write bitmap [+ padding] [+ oid] + data */ /* PG73FORMAT: write bitmap [+ padding] [+ oid] + data */
XLogRegisterData((char *) old_key_tuple->t_data + offsetof(HeapTupleHeaderData, t_bits), XLogRegisterData((char *) old_key_tuple->t_data + SizeofHeapTupleHeader,
old_key_tuple->t_len - offsetof(HeapTupleHeaderData, t_bits)); old_key_tuple->t_len - SizeofHeapTupleHeader);
} }
recptr = XLogInsert(RM_HEAP_ID, info); recptr = XLogInsert(RM_HEAP_ID, info);
@ -7351,7 +7351,7 @@ heap_xlog_insert(XLogReaderState *record)
xl_heap_insert *xlrec = (xl_heap_insert *) XLogRecGetData(record); xl_heap_insert *xlrec = (xl_heap_insert *) XLogRecGetData(record);
Buffer buffer; Buffer buffer;
Page page; Page page;
struct union
{ {
HeapTupleHeaderData hdr; HeapTupleHeaderData hdr;
char data[MaxHeapTupleSize]; char data[MaxHeapTupleSize];
@ -7415,12 +7415,12 @@ heap_xlog_insert(XLogReaderState *record)
data += SizeOfHeapHeader; data += SizeOfHeapHeader;
htup = &tbuf.hdr; htup = &tbuf.hdr;
MemSet((char *) htup, 0, sizeof(HeapTupleHeaderData)); MemSet((char *) htup, 0, SizeofHeapTupleHeader);
/* PG73FORMAT: get bitmap [+ padding] [+ oid] + data */ /* PG73FORMAT: get bitmap [+ padding] [+ oid] + data */
memcpy((char *) htup + offsetof(HeapTupleHeaderData, t_bits), memcpy((char *) htup + SizeofHeapTupleHeader,
data, data,
newlen); newlen);
newlen += offsetof(HeapTupleHeaderData, t_bits); newlen += SizeofHeapTupleHeader;
htup->t_infomask2 = xlhdr.t_infomask2; htup->t_infomask2 = xlhdr.t_infomask2;
htup->t_infomask = xlhdr.t_infomask; htup->t_infomask = xlhdr.t_infomask;
htup->t_hoff = xlhdr.t_hoff; htup->t_hoff = xlhdr.t_hoff;
@ -7469,7 +7469,7 @@ heap_xlog_multi_insert(XLogReaderState *record)
BlockNumber blkno; BlockNumber blkno;
Buffer buffer; Buffer buffer;
Page page; Page page;
struct union
{ {
HeapTupleHeaderData hdr; HeapTupleHeaderData hdr;
char data[MaxHeapTupleSize]; char data[MaxHeapTupleSize];
@ -7548,14 +7548,14 @@ heap_xlog_multi_insert(XLogReaderState *record)
newlen = xlhdr->datalen; newlen = xlhdr->datalen;
Assert(newlen <= MaxHeapTupleSize); Assert(newlen <= MaxHeapTupleSize);
htup = &tbuf.hdr; htup = &tbuf.hdr;
MemSet((char *) htup, 0, sizeof(HeapTupleHeaderData)); MemSet((char *) htup, 0, SizeofHeapTupleHeader);
/* PG73FORMAT: get bitmap [+ padding] [+ oid] + data */ /* PG73FORMAT: get bitmap [+ padding] [+ oid] + data */
memcpy((char *) htup + offsetof(HeapTupleHeaderData, t_bits), memcpy((char *) htup + SizeofHeapTupleHeader,
(char *) tupdata, (char *) tupdata,
newlen); newlen);
tupdata += newlen; tupdata += newlen;
newlen += offsetof(HeapTupleHeaderData, t_bits); newlen += SizeofHeapTupleHeader;
htup->t_infomask2 = xlhdr->t_infomask2; htup->t_infomask2 = xlhdr->t_infomask2;
htup->t_infomask = xlhdr->t_infomask; htup->t_infomask = xlhdr->t_infomask;
htup->t_hoff = xlhdr->t_hoff; htup->t_hoff = xlhdr->t_hoff;
@ -7618,7 +7618,7 @@ heap_xlog_update(XLogReaderState *record, bool hot_update)
uint16 prefixlen = 0, uint16 prefixlen = 0,
suffixlen = 0; suffixlen = 0;
char *newp; char *newp;
struct union
{ {
HeapTupleHeaderData hdr; HeapTupleHeaderData hdr;
char data[MaxHeapTupleSize]; char data[MaxHeapTupleSize];
@ -7780,19 +7780,19 @@ heap_xlog_update(XLogReaderState *record, bool hot_update)
Assert(tuplen <= MaxHeapTupleSize); Assert(tuplen <= MaxHeapTupleSize);
htup = &tbuf.hdr; htup = &tbuf.hdr;
MemSet((char *) htup, 0, sizeof(HeapTupleHeaderData)); MemSet((char *) htup, 0, SizeofHeapTupleHeader);
/* /*
* Reconstruct the new tuple using the prefix and/or suffix from the * Reconstruct the new tuple using the prefix and/or suffix from the
* old tuple, and the data stored in the WAL record. * old tuple, and the data stored in the WAL record.
*/ */
newp = (char *) htup + offsetof(HeapTupleHeaderData, t_bits); newp = (char *) htup + SizeofHeapTupleHeader;
if (prefixlen > 0) if (prefixlen > 0)
{ {
int len; int len;
/* copy bitmap [+ padding] [+ oid] from WAL record */ /* copy bitmap [+ padding] [+ oid] from WAL record */
len = xlhdr.t_hoff - offsetof(HeapTupleHeaderData, t_bits); len = xlhdr.t_hoff - SizeofHeapTupleHeader;
memcpy(newp, recdata, len); memcpy(newp, recdata, len);
recdata += len; recdata += len;
newp += len; newp += len;
@ -7802,7 +7802,7 @@ heap_xlog_update(XLogReaderState *record, bool hot_update)
newp += prefixlen; newp += prefixlen;
/* copy new tuple data from WAL record */ /* copy new tuple data from WAL record */
len = tuplen - (xlhdr.t_hoff - offsetof(HeapTupleHeaderData, t_bits)); len = tuplen - (xlhdr.t_hoff - SizeofHeapTupleHeader);
memcpy(newp, recdata, len); memcpy(newp, recdata, len);
recdata += len; recdata += len;
newp += len; newp += len;
@ -7823,7 +7823,7 @@ heap_xlog_update(XLogReaderState *record, bool hot_update)
if (suffixlen > 0) if (suffixlen > 0)
memcpy(newp, (char *) oldtup.t_data + oldtup.t_len - suffixlen, suffixlen); memcpy(newp, (char *) oldtup.t_data + oldtup.t_len - suffixlen, suffixlen);
newlen = offsetof(HeapTupleHeaderData, t_bits) + tuplen + prefixlen + suffixlen; newlen = SizeofHeapTupleHeader + tuplen + prefixlen + suffixlen;
htup->t_infomask2 = xlhdr.t_infomask2; htup->t_infomask2 = xlhdr.t_infomask2;
htup->t_infomask = xlhdr.t_infomask; htup->t_infomask = xlhdr.t_infomask;
htup->t_hoff = xlhdr.t_hoff; htup->t_hoff = xlhdr.t_hoff;

View File

@ -677,7 +677,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup,
*/ */
/* compute header overhead --- this should match heap_form_tuple() */ /* compute header overhead --- this should match heap_form_tuple() */
hoff = offsetof(HeapTupleHeaderData, t_bits); hoff = SizeofHeapTupleHeader;
if (has_nulls) if (has_nulls)
hoff += BITMAPLEN(numAttrs); hoff += BITMAPLEN(numAttrs);
if (newtup->t_data->t_infomask & HEAP_HASOID) if (newtup->t_data->t_infomask & HEAP_HASOID)
@ -963,7 +963,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup,
* different conclusion about the size of the null bitmap, or even * different conclusion about the size of the null bitmap, or even
* whether there needs to be one at all. * whether there needs to be one at all.
*/ */
new_header_len = offsetof(HeapTupleHeaderData, t_bits); new_header_len = SizeofHeapTupleHeader;
if (has_nulls) if (has_nulls)
new_header_len += BITMAPLEN(numAttrs); new_header_len += BITMAPLEN(numAttrs);
if (olddata->t_infomask & HEAP_HASOID) if (olddata->t_infomask & HEAP_HASOID)
@ -986,7 +986,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup,
/* /*
* Copy the existing tuple header, but adjust natts and t_hoff. * Copy the existing tuple header, but adjust natts and t_hoff.
*/ */
memcpy(new_data, olddata, offsetof(HeapTupleHeaderData, t_bits)); memcpy(new_data, olddata, SizeofHeapTupleHeader);
HeapTupleHeaderSetNatts(new_data, numAttrs); HeapTupleHeaderSetNatts(new_data, numAttrs);
new_data->t_hoff = new_header_len; new_data->t_hoff = new_header_len;
if (olddata->t_infomask & HEAP_HASOID) if (olddata->t_infomask & HEAP_HASOID)
@ -1196,7 +1196,7 @@ toast_flatten_tuple_to_datum(HeapTupleHeader tup,
* *
* This should match the reconstruction code in toast_insert_or_update. * This should match the reconstruction code in toast_insert_or_update.
*/ */
new_header_len = offsetof(HeapTupleHeaderData, t_bits); new_header_len = SizeofHeapTupleHeader;
if (has_nulls) if (has_nulls)
new_header_len += BITMAPLEN(numAttrs); new_header_len += BITMAPLEN(numAttrs);
if (tup->t_infomask & HEAP_HASOID) if (tup->t_infomask & HEAP_HASOID)
@ -1211,7 +1211,7 @@ toast_flatten_tuple_to_datum(HeapTupleHeader tup,
/* /*
* Copy the existing tuple header, but adjust natts and t_hoff. * Copy the existing tuple header, but adjust natts and t_hoff.
*/ */
memcpy(new_data, tup, offsetof(HeapTupleHeaderData, t_bits)); memcpy(new_data, tup, SizeofHeapTupleHeader);
HeapTupleHeaderSetNatts(new_data, numAttrs); HeapTupleHeaderSetNatts(new_data, numAttrs);
new_data->t_hoff = new_header_len; new_data->t_hoff = new_header_len;
if (tup->t_infomask & HEAP_HASOID) if (tup->t_infomask & HEAP_HASOID)

View File

@ -447,7 +447,7 @@ needs_toast_table(Relation rel)
return false; /* nothing to toast? */ return false; /* nothing to toast? */
if (maxlength_unknown) if (maxlength_unknown)
return true; /* any unlimited-length attrs? */ return true; /* any unlimited-length attrs? */
tuple_length = MAXALIGN(offsetof(HeapTupleHeaderData, t_bits) + tuple_length = MAXALIGN(SizeofHeapTupleHeader +
BITMAPLEN(tupdesc->natts)) + BITMAPLEN(tupdesc->natts)) +
MAXALIGN(data_length); MAXALIGN(data_length);
return (tuple_length > TOAST_TUPLE_THRESHOLD); return (tuple_length > TOAST_TUPLE_THRESHOLD);

View File

@ -439,7 +439,7 @@ ExecChooseHashTableSize(double ntuples, int tupwidth, bool useskew,
* don't count palloc overhead either. * don't count palloc overhead either.
*/ */
tupsize = HJTUPLE_OVERHEAD + tupsize = HJTUPLE_OVERHEAD +
MAXALIGN(sizeof(MinimalTupleData)) + MAXALIGN(SizeofMinimalTupleHeader) +
MAXALIGN(tupwidth); MAXALIGN(tupwidth);
inner_rel_bytes = ntuples * tupsize; inner_rel_bytes = ntuples * tupsize;

View File

@ -4036,11 +4036,11 @@ set_rel_width(PlannerInfo *root, RelOptInfo *rel)
/* /*
* If we have a whole-row reference, estimate its width as the sum of * If we have a whole-row reference, estimate its width as the sum of
* per-column widths plus sizeof(HeapTupleHeaderData). * per-column widths plus heap tuple header overhead.
*/ */
if (have_wholerow_var) if (have_wholerow_var)
{ {
int32 wholerow_width = sizeof(HeapTupleHeaderData); int32 wholerow_width = MAXALIGN(SizeofHeapTupleHeader);
if (reloid != InvalidOid) if (reloid != InvalidOid)
{ {
@ -4078,7 +4078,7 @@ set_rel_width(PlannerInfo *root, RelOptInfo *rel)
static double static double
relation_byte_size(double tuples, int width) relation_byte_size(double tuples, int width)
{ {
return tuples * (MAXALIGN(width) + MAXALIGN(sizeof(HeapTupleHeaderData))); return tuples * (MAXALIGN(width) + MAXALIGN(SizeofHeapTupleHeader));
} }
/* /*

View File

@ -2755,7 +2755,7 @@ choose_hashed_grouping(PlannerInfo *root,
*/ */
/* Estimate per-hash-entry space at tuple width... */ /* Estimate per-hash-entry space at tuple width... */
hashentrysize = MAXALIGN(path_width) + MAXALIGN(sizeof(MinimalTupleData)); hashentrysize = MAXALIGN(path_width) + MAXALIGN(SizeofMinimalTupleHeader);
/* plus space for pass-by-ref transition values... */ /* plus space for pass-by-ref transition values... */
hashentrysize += agg_costs->transitionSpace; hashentrysize += agg_costs->transitionSpace;
/* plus the per-hash-entry overhead */ /* plus the per-hash-entry overhead */
@ -2923,7 +2923,7 @@ choose_hashed_distinct(PlannerInfo *root,
*/ */
/* Estimate per-hash-entry space at tuple width... */ /* Estimate per-hash-entry space at tuple width... */
hashentrysize = MAXALIGN(path_width) + MAXALIGN(sizeof(MinimalTupleData)); hashentrysize = MAXALIGN(path_width) + MAXALIGN(SizeofMinimalTupleHeader);
/* plus the per-hash-entry overhead */ /* plus the per-hash-entry overhead */
hashentrysize += hash_agg_entry_size(0); hashentrysize += hash_agg_entry_size(0);

View File

@ -974,12 +974,12 @@ subplan_is_hashable(Plan *plan)
/* /*
* The estimated size of the subquery result must fit in work_mem. (Note: * The estimated size of the subquery result must fit in work_mem. (Note:
* we use sizeof(HeapTupleHeaderData) here even though the tuples will * we use heap tuple overhead here even though the tuples will actually be
* actually be stored as MinimalTuples; this provides some fudge factor * stored as MinimalTuples; this provides some fudge factor for hashtable
* for hashtable overhead.) * overhead.)
*/ */
subquery_size = plan->plan_rows * subquery_size = plan->plan_rows *
(MAXALIGN(plan->plan_width) + MAXALIGN(sizeof(HeapTupleHeaderData))); (MAXALIGN(plan->plan_width) + MAXALIGN(SizeofHeapTupleHeader));
if (subquery_size > work_mem * 1024L) if (subquery_size > work_mem * 1024L)
return false; return false;

View File

@ -832,7 +832,7 @@ choose_hashed_setop(PlannerInfo *root, List *groupClauses,
* Don't do it if it doesn't look like the hashtable will fit into * Don't do it if it doesn't look like the hashtable will fit into
* work_mem. * work_mem.
*/ */
hashentrysize = MAXALIGN(input_plan->plan_width) + MAXALIGN(sizeof(MinimalTupleData)); hashentrysize = MAXALIGN(input_plan->plan_width) + MAXALIGN(SizeofMinimalTupleHeader);
if (hashentrysize * dNumGroups > work_mem * 1024L) if (hashentrysize * dNumGroups > work_mem * 1024L)
return false; return false;

View File

@ -508,7 +508,7 @@ estimate_rel_size(Relation rel, int32 *attr_widths,
int32 tuple_width; int32 tuple_width;
tuple_width = get_rel_data_width(rel, attr_widths); tuple_width = get_rel_data_width(rel, attr_widths);
tuple_width += sizeof(HeapTupleHeaderData); tuple_width += MAXALIGN(SizeofHeapTupleHeader);
tuple_width += sizeof(ItemIdData); tuple_width += sizeof(ItemIdData);
/* note: integer division is intentional here */ /* note: integer division is intentional here */
density = (BLCKSZ - SizeOfPageHeaderData) / tuple_width; density = (BLCKSZ - SizeOfPageHeaderData) / tuple_width;

View File

@ -765,21 +765,19 @@ DecodeMultiInsert(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
* transactions. * transactions.
*/ */
tuple->tuple.t_tableOid = InvalidOid; tuple->tuple.t_tableOid = InvalidOid;
tuple->tuple.t_data = &tuple->header; tuple->tuple.t_data = &tuple->t_data.header;
tuple->tuple.t_len = datalen tuple->tuple.t_len = datalen + SizeofHeapTupleHeader;
+ offsetof(HeapTupleHeaderData, t_bits);
memset(&tuple->header, 0, sizeof(HeapTupleHeaderData)); memset(&tuple->t_data.header, 0, SizeofHeapTupleHeader);
memcpy((char *) &tuple->header memcpy((char *) &tuple->t_data.header + SizeofHeapTupleHeader,
+ offsetof(HeapTupleHeaderData, t_bits),
(char *) data, (char *) data,
datalen); datalen);
data += datalen; data += datalen;
tuple->header.t_infomask = xlhdr->t_infomask; tuple->t_data.header.t_infomask = xlhdr->t_infomask;
tuple->header.t_infomask2 = xlhdr->t_infomask2; tuple->t_data.header.t_infomask2 = xlhdr->t_infomask2;
tuple->header.t_hoff = xlhdr->t_hoff; tuple->t_data.header.t_hoff = xlhdr->t_hoff;
} }
/* /*
@ -815,27 +813,27 @@ DecodeXLogTuple(char *data, Size len, ReorderBufferTupleBuf *tuple)
Assert(datalen >= 0); Assert(datalen >= 0);
Assert(datalen <= MaxHeapTupleSize); Assert(datalen <= MaxHeapTupleSize);
tuple->tuple.t_len = datalen + offsetof(HeapTupleHeaderData, t_bits); tuple->tuple.t_len = datalen + SizeofHeapTupleHeader;
/* not a disk based tuple */ /* not a disk based tuple */
ItemPointerSetInvalid(&tuple->tuple.t_self); ItemPointerSetInvalid(&tuple->tuple.t_self);
/* we can only figure this out after reassembling the transactions */ /* we can only figure this out after reassembling the transactions */
tuple->tuple.t_tableOid = InvalidOid; tuple->tuple.t_tableOid = InvalidOid;
tuple->tuple.t_data = &tuple->header; tuple->tuple.t_data = &tuple->t_data.header;
/* data is not stored aligned, copy to aligned storage */ /* data is not stored aligned, copy to aligned storage */
memcpy((char *) &xlhdr, memcpy((char *) &xlhdr,
data, data,
SizeOfHeapHeader); SizeOfHeapHeader);
memset(&tuple->header, 0, sizeof(HeapTupleHeaderData)); memset(&tuple->t_data.header, 0, SizeofHeapTupleHeader);
memcpy((char *) &tuple->header + offsetof(HeapTupleHeaderData, t_bits), memcpy((char *) &tuple->t_data.header + SizeofHeapTupleHeader,
data + SizeOfHeapHeader, data + SizeOfHeapHeader,
datalen); datalen);
tuple->header.t_infomask = xlhdr.t_infomask; tuple->t_data.header.t_infomask = xlhdr.t_infomask;
tuple->header.t_infomask2 = xlhdr.t_infomask2; tuple->t_data.header.t_infomask2 = xlhdr.t_infomask2;
tuple->header.t_hoff = xlhdr.t_hoff; tuple->t_data.header.t_hoff = xlhdr.t_hoff;
} }

View File

@ -2014,14 +2014,12 @@ ReorderBufferSerializeChange(ReorderBuffer *rb, ReorderBufferTXN *txn,
newtup = change->data.tp.newtuple; newtup = change->data.tp.newtuple;
if (oldtup) if (oldtup)
oldlen = offsetof(ReorderBufferTupleBuf, data) oldlen = offsetof(ReorderBufferTupleBuf, t_data) +
+oldtup->tuple.t_len oldtup->tuple.t_len;
- offsetof(HeapTupleHeaderData, t_bits);
if (newtup) if (newtup)
newlen = offsetof(ReorderBufferTupleBuf, data) newlen = offsetof(ReorderBufferTupleBuf, t_data) +
+newtup->tuple.t_len newtup->tuple.t_len;
- offsetof(HeapTupleHeaderData, t_bits);
sz += oldlen; sz += oldlen;
sz += newlen; sz += newlen;
@ -2262,27 +2260,25 @@ ReorderBufferRestoreChange(ReorderBuffer *rb, ReorderBufferTXN *txn,
case REORDER_BUFFER_CHANGE_DELETE: case REORDER_BUFFER_CHANGE_DELETE:
if (change->data.tp.newtuple) if (change->data.tp.newtuple)
{ {
Size len = offsetof(ReorderBufferTupleBuf, data) Size len = offsetof(ReorderBufferTupleBuf, t_data) +
+((ReorderBufferTupleBuf *) data)->tuple.t_len ((ReorderBufferTupleBuf *) data)->tuple.t_len;
- offsetof(HeapTupleHeaderData, t_bits);
change->data.tp.newtuple = ReorderBufferGetTupleBuf(rb); change->data.tp.newtuple = ReorderBufferGetTupleBuf(rb);
memcpy(change->data.tp.newtuple, data, len); memcpy(change->data.tp.newtuple, data, len);
change->data.tp.newtuple->tuple.t_data = change->data.tp.newtuple->tuple.t_data =
&change->data.tp.newtuple->header; &change->data.tp.newtuple->t_data.header;
data += len; data += len;
} }
if (change->data.tp.oldtuple) if (change->data.tp.oldtuple)
{ {
Size len = offsetof(ReorderBufferTupleBuf, data) Size len = offsetof(ReorderBufferTupleBuf, t_data) +
+((ReorderBufferTupleBuf *) data)->tuple.t_len ((ReorderBufferTupleBuf *) data)->tuple.t_len;
- offsetof(HeapTupleHeaderData, t_bits);
change->data.tp.oldtuple = ReorderBufferGetTupleBuf(rb); change->data.tp.oldtuple = ReorderBufferGetTupleBuf(rb);
memcpy(change->data.tp.oldtuple, data, len); memcpy(change->data.tp.oldtuple, data, len);
change->data.tp.oldtuple->tuple.t_data = change->data.tp.oldtuple->tuple.t_data =
&change->data.tp.oldtuple->header; &change->data.tp.oldtuple->t_data.header;
data += len; data += len;
} }
break; break;
@ -2660,7 +2656,7 @@ ReorderBufferToastReplace(ReorderBuffer *rb, ReorderBufferTXN *txn,
*/ */
tmphtup = heap_form_tuple(desc, attrs, isnull); tmphtup = heap_form_tuple(desc, attrs, isnull);
Assert(newtup->tuple.t_len <= MaxHeapTupleSize); Assert(newtup->tuple.t_len <= MaxHeapTupleSize);
Assert(&newtup->header == newtup->tuple.t_data); Assert(&newtup->t_data.header == newtup->tuple.t_data);
memcpy(newtup->tuple.t_data, tmphtup->t_data, tmphtup->t_len); memcpy(newtup->tuple.t_data, tmphtup->t_data, tmphtup->t_len);
newtup->tuple.t_len = tmphtup->t_len; newtup->tuple.t_len = tmphtup->t_len;

View File

@ -84,9 +84,9 @@ suppress_redundant_updates_trigger(PG_FUNCTION_ARGS)
HeapTupleHeaderGetNatts(oldheader)) && HeapTupleHeaderGetNatts(oldheader)) &&
((newheader->t_infomask & ~HEAP_XACT_MASK) == ((newheader->t_infomask & ~HEAP_XACT_MASK) ==
(oldheader->t_infomask & ~HEAP_XACT_MASK)) && (oldheader->t_infomask & ~HEAP_XACT_MASK)) &&
memcmp(((char *) newheader) + offsetof(HeapTupleHeaderData, t_bits), memcmp(((char *) newheader) + SizeofHeapTupleHeader,
((char *) oldheader) + offsetof(HeapTupleHeaderData, t_bits), ((char *) oldheader) + SizeofHeapTupleHeader,
newtuple->t_len - offsetof(HeapTupleHeaderData, t_bits)) == 0) newtuple->t_len - SizeofHeapTupleHeader) == 0)
{ {
/* ... then suppress the update */ /* ... then suppress the update */
rettuple = NULL; rettuple = NULL;

View File

@ -150,13 +150,15 @@ struct HeapTupleHeaderData
/* ^ - 23 bytes - ^ */ /* ^ - 23 bytes - ^ */
bits8 t_bits[1]; /* bitmap of NULLs -- VARIABLE LENGTH */ bits8 t_bits[FLEXIBLE_ARRAY_MEMBER]; /* bitmap of NULLs */
/* MORE DATA FOLLOWS AT END OF STRUCT */ /* MORE DATA FOLLOWS AT END OF STRUCT */
}; };
/* typedef appears in tupbasics.h */ /* typedef appears in tupbasics.h */
#define SizeofHeapTupleHeader offsetof(HeapTupleHeaderData, t_bits)
/* /*
* information stored in t_infomask: * information stored in t_infomask:
*/ */
@ -498,7 +500,7 @@ do { \
* you can, say, fit 2 tuples of size MaxHeapTupleSize/2 on the same page. * you can, say, fit 2 tuples of size MaxHeapTupleSize/2 on the same page.
*/ */
#define MaxHeapTupleSize (BLCKSZ - MAXALIGN(SizeOfPageHeaderData + sizeof(ItemIdData))) #define MaxHeapTupleSize (BLCKSZ - MAXALIGN(SizeOfPageHeaderData + sizeof(ItemIdData)))
#define MinHeapTupleSize MAXALIGN(offsetof(HeapTupleHeaderData, t_bits)) #define MinHeapTupleSize MAXALIGN(SizeofHeapTupleHeader)
/* /*
* MaxHeapTuplesPerPage is an upper bound on the number of tuples that can * MaxHeapTuplesPerPage is an upper bound on the number of tuples that can
@ -513,7 +515,7 @@ do { \
*/ */
#define MaxHeapTuplesPerPage \ #define MaxHeapTuplesPerPage \
((int) ((BLCKSZ - SizeOfPageHeaderData) / \ ((int) ((BLCKSZ - SizeOfPageHeaderData) / \
(MAXALIGN(offsetof(HeapTupleHeaderData, t_bits)) + sizeof(ItemIdData)))) (MAXALIGN(SizeofHeapTupleHeader) + sizeof(ItemIdData))))
/* /*
* MaxAttrSize is a somewhat arbitrary upper limit on the declared size of * MaxAttrSize is a somewhat arbitrary upper limit on the declared size of
@ -579,13 +581,15 @@ struct MinimalTupleData
/* ^ - 23 bytes - ^ */ /* ^ - 23 bytes - ^ */
bits8 t_bits[1]; /* bitmap of NULLs -- VARIABLE LENGTH */ bits8 t_bits[FLEXIBLE_ARRAY_MEMBER]; /* bitmap of NULLs */
/* MORE DATA FOLLOWS AT END OF STRUCT */ /* MORE DATA FOLLOWS AT END OF STRUCT */
}; };
/* typedef appears in htup.h */ /* typedef appears in htup.h */
#define SizeofMinimalTupleHeader offsetof(MinimalTupleData, t_bits)
/* /*
* GETSTRUCT - given a HeapTuple pointer, return address of the user data * GETSTRUCT - given a HeapTuple pointer, return address of the user data

View File

@ -90,7 +90,7 @@
#define TOAST_MAX_CHUNK_SIZE \ #define TOAST_MAX_CHUNK_SIZE \
(EXTERN_TUPLE_MAX_SIZE - \ (EXTERN_TUPLE_MAX_SIZE - \
MAXALIGN(offsetof(HeapTupleHeaderData, t_bits)) - \ MAXALIGN(SizeofHeapTupleHeader) - \
sizeof(Oid) - \ sizeof(Oid) - \
sizeof(int32) - \ sizeof(int32) - \
VARHDRSZ) VARHDRSZ)

View File

@ -28,8 +28,12 @@ typedef struct ReorderBufferTupleBuf
/* tuple, stored sequentially */ /* tuple, stored sequentially */
HeapTupleData tuple; HeapTupleData tuple;
HeapTupleHeaderData header; union
char data[MaxHeapTupleSize]; {
HeapTupleHeaderData header;
char data[MaxHeapTupleSize];
double align_it; /* ensure t_data is MAXALIGN'd */
} t_data;
} ReorderBufferTupleBuf; } ReorderBufferTupleBuf;
/* /*
@ -77,7 +81,7 @@ typedef struct ReorderBufferChange
RelFileNode relnode; RelFileNode relnode;
/* no previously reassembled toast chunks are necessary anymore */ /* no previously reassembled toast chunks are necessary anymore */
bool clear_toast_afterwards; bool clear_toast_afterwards;
/* valid for DELETE || UPDATE */ /* valid for DELETE || UPDATE */
ReorderBufferTupleBuf *oldtuple; ReorderBufferTupleBuf *oldtuple;