@ -2640,7 +2640,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 ;
@ -2659,7 +2659,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 ] ) ;
@ -2682,11 +2682,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 1 B or 4 B header . Convert 4 B header of short
* tuples to 1 B
*/
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 4 B header
*/
if ( ! formnewtup )
return itup ;
@ -2696,6 +2717,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 1 B
* header and 4 B headers . But the corresponding index tuple should always
* have such varlena ' s with 1 B headers . So , if there is a short varlena
* with 4 B header , we need to convert it for for fingerprinting .
*
* Note that we rely on deterministic index_form_tuple ( ) TOAST compression
* of normalized input .
*/
@ -2704,7 +2730,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 ;