mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 11:03:19 +03:00
amcheck: Support for different header sizes of short varlena datum
In the heap, tuples may contain short varlena datum with both 1B header and 4B headers. But the corresponding index tuple should always have such varlena's with 1B headers. So, for fingerprinting, we need to convert. Backpatch to all supported versions. Discussion: https://postgr.es/m/flat/7bdbe559-d61a-4ae4-a6e1-48abdf3024cc%40postgrespro.ru Author: Michael Zhilin Reviewed-by: Alexander Lakhin, Andrey Borodin, Jian He, Alexander Korotkov Backpatch-through: 12
This commit is contained in:
@ -2058,7 +2058,7 @@ bt_normalize_tuple(BtreeCheckState *state, IndexTuple itup)
|
||||
TupleDesc tupleDescriptor = RelationGetDescr(state->rel);
|
||||
Datum normalized[INDEX_MAX_KEYS];
|
||||
bool isnull[INDEX_MAX_KEYS];
|
||||
bool toast_free[INDEX_MAX_KEYS];
|
||||
bool need_free[INDEX_MAX_KEYS];
|
||||
bool formnewtup = false;
|
||||
IndexTuple reformed;
|
||||
int i;
|
||||
@ -2074,7 +2074,7 @@ bt_normalize_tuple(BtreeCheckState *state, IndexTuple itup)
|
||||
att = TupleDescAttr(tupleDescriptor, i);
|
||||
|
||||
/* Assume untoasted/already normalized datum initially */
|
||||
toast_free[i] = false;
|
||||
need_free[i] = false;
|
||||
normalized[i] = index_getattr(itup, att->attnum,
|
||||
tupleDescriptor,
|
||||
&isnull[i]);
|
||||
@ -2097,11 +2097,32 @@ bt_normalize_tuple(BtreeCheckState *state, IndexTuple itup)
|
||||
{
|
||||
formnewtup = true;
|
||||
normalized[i] = PointerGetDatum(PG_DETOAST_DATUM(normalized[i]));
|
||||
toast_free[i] = true;
|
||||
need_free[i] = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Short tuples may have 1B or 4B header. Convert 4B header of short
|
||||
* tuples to 1B
|
||||
*/
|
||||
else if (VARATT_CAN_MAKE_SHORT(DatumGetPointer(normalized[i])))
|
||||
{
|
||||
/* convert to short varlena */
|
||||
Size len = VARATT_CONVERTED_SHORT_SIZE(DatumGetPointer(normalized[i]));
|
||||
char *data = palloc(len);
|
||||
|
||||
SET_VARSIZE_SHORT(data, len);
|
||||
memcpy(data + 1, VARDATA(DatumGetPointer(normalized[i])), len - 1);
|
||||
|
||||
formnewtup = true;
|
||||
normalized[i] = PointerGetDatum(data);
|
||||
need_free[i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Easier case: Tuple has varlena datums, none of which are compressed */
|
||||
/*
|
||||
* Easier case: Tuple has varlena datums, none of which are compressed or
|
||||
* short with 4B header
|
||||
*/
|
||||
if (!formnewtup)
|
||||
return itup;
|
||||
|
||||
@ -2111,6 +2132,11 @@ bt_normalize_tuple(BtreeCheckState *state, IndexTuple itup)
|
||||
* (normalized input datums). This is rather naive, but shouldn't be
|
||||
* necessary too often.
|
||||
*
|
||||
* In the heap, tuples may contain short varlena datums with both 1B
|
||||
* header and 4B headers. But the corresponding index tuple should always
|
||||
* have such varlena's with 1B headers. So, if there is a short varlena
|
||||
* with 4B header, we need to convert it for for fingerprinting.
|
||||
*
|
||||
* Note that we rely on deterministic index_form_tuple() TOAST compression
|
||||
* of normalized input.
|
||||
*/
|
||||
@ -2119,7 +2145,7 @@ bt_normalize_tuple(BtreeCheckState *state, IndexTuple itup)
|
||||
|
||||
/* Cannot leak memory here */
|
||||
for (i = 0; i < tupleDescriptor->natts; i++)
|
||||
if (toast_free[i])
|
||||
if (need_free[i])
|
||||
pfree(DatumGetPointer(normalized[i]));
|
||||
|
||||
return reformed;
|
||||
|
Reference in New Issue
Block a user