diff --git a/src/backend/statistics/mcv.c b/src/backend/statistics/mcv.c index 5fe61ea0a4..01ea05b486 100644 --- a/src/backend/statistics/mcv.c +++ b/src/backend/statistics/mcv.c @@ -57,10 +57,10 @@ /* * Macros for convenient access to parts of a serialized MCV item. */ -#define ITEM_INDEXES(item) ((uint16 *) (item)) -#define ITEM_NULLS(item,ndims) ((bool *) (ITEM_INDEXES(item) + (ndims))) -#define ITEM_FREQUENCY(item,ndims) ((double *) (ITEM_NULLS(item, ndims) + (ndims))) -#define ITEM_BASE_FREQUENCY(item,ndims) ((double *) (ITEM_FREQUENCY(item, ndims) + 1)) +#define ITEM_INDEXES(item) ((char *) item) +#define ITEM_NULLS(item,ndims) (ITEM_INDEXES(item) + (ndims) * sizeof(uint16)) +#define ITEM_FREQUENCY(item,ndims) (ITEM_NULLS(item, ndims) + (ndims) * sizeof(bool)) +#define ITEM_BASE_FREQUENCY(item,ndims) (ITEM_FREQUENCY(item, ndims) + sizeof(double)) /* * Used to compute size of serialized MCV list representation. @@ -751,6 +751,7 @@ statext_mcv_serialize(MCVList *mcvlist, VacAttrStats **stats) for (i = 0; i < mcvlist->nitems; i++) { MCVItem *mcvitem = &mcvlist->items[i]; + uint16 *indexes = (uint16 *) ITEM_INDEXES(item); /* don't write beyond the allocated space */ Assert(ptr <= raw + total_length - itemsize); @@ -773,10 +774,10 @@ statext_mcv_serialize(MCVList *mcvlist, VacAttrStats **stats) Assert(value != NULL); /* serialization or deduplication error */ /* compute index within the array */ - ITEM_INDEXES(item)[dim] = (uint16) (value - values[dim]); + indexes[dim] = (uint16) (value - values[dim]); /* check the index is within expected bounds */ - Assert(ITEM_INDEXES(item)[dim] < info[dim].nvalues); + Assert(indexes[dim] < info[dim].nvalues); } /* copy NULL and frequency flags into the item */ @@ -1087,10 +1088,13 @@ statext_mcv_deserialize(bytea *data) item->isnull = (bool *) isnullptr; isnullptr += MAXALIGN(sizeof(bool) * ndims); + /* + * To access indexes, we can just point to the right place (we can + * do this, because we ensure alignment during serialization). + */ + indexes = (uint16 *) ITEM_INDEXES(ptr); - /* just point to the right place */ - indexes = ITEM_INDEXES(ptr); - + /* The remaining fields may not be aligned, though. */ memcpy(item->isnull, ITEM_NULLS(ptr, ndims), sizeof(bool) * ndims); memcpy(&item->frequency, ITEM_FREQUENCY(ptr, ndims), sizeof(double)); memcpy(&item->base_frequency, ITEM_BASE_FREQUENCY(ptr, ndims), sizeof(double));