@ -50,7 +50,7 @@
*/
typedef struct toast_compress_header
{
int32 vl_len_ ; /* varlena header (do not touch directly!) */
int32 vl_len_ ; /* varlena header (do not touch directly!) */
int32 rawsize ;
} toast_compress_header ;
@ -58,12 +58,12 @@ typedef struct toast_compress_header
* Utilities for manipulation of header information for compressed
* toast entries .
*/
# define TOAST_COMPRESS_HDRSZ ((int32) sizeof(toast_compress_header))
# define TOAST_COMPRESS_RAWSIZE(ptr) (((toast_compress_header *) ptr )->rawsize)
# define TOAST_COMPRESS_HDRSZ ((int32) sizeof(toast_compress_header))
# define TOAST_COMPRESS_RAWSIZE(ptr) (((toast_compress_header *) (ptr) )->rawsize)
# define TOAST_COMPRESS_RAWDATA(ptr) \
( ( ( char * ) ptr ) + TOAST_COMPRESS_HDRSZ )
( ( ( char * ) ( ptr ) ) + TOAST_COMPRESS_HDRSZ )
# define TOAST_COMPRESS_SET_RAWSIZE(ptr, len) \
( ( ( toast_compress_header * ) ptr ) - > rawsize = len )
( ( ( toast_compress_header * ) ( ptr ) ) - > rawsize = ( len ) )
static void toast_delete_datum ( Relation rel , Datum value ) ;
static Datum toast_save_datum ( Relation rel , Datum value ,
@ -90,8 +90,9 @@ static void toast_close_indexes(Relation *toastidxs, int num_indexes,
*
* This will return a datum that contains all the data internally , ie , not
* relying on external storage or memory , but it can still be compressed or
* have a short header .
- - - - - - - - - -
* have a short header . Note some callers assume that if the input is an
* EXTERNAL datum , the result will be a pfree ' able chunk .
* - - - - - - - - - -
*/
struct varlena *
heap_tuple_fetch_attr ( struct varlena * attr )
@ -108,9 +109,7 @@ heap_tuple_fetch_attr(struct varlena * attr)
else if ( VARATT_IS_EXTERNAL_INDIRECT ( attr ) )
{
/*
* copy into the caller ' s memory context . That ' s not required in all
* cases but sufficient for now since this is mainly used when we need
* to persist a Datum for unusually long time , like in a HOLD cursor .
* This is an indirect pointer - - - dereference it
*/
struct varatt_indirect redirect ;
@ -120,11 +119,14 @@ heap_tuple_fetch_attr(struct varlena * attr)
/* nested indirect Datums aren't allowed */
Assert ( ! VARATT_IS_EXTERNAL_INDIRECT ( attr ) ) ;
/* doesn't make much sense, but better handle it */
if ( VARATT_IS_EXTERNAL_ONDISK ( attr ) )
/* recurse if value is still external in some other way */
if ( VARATT_IS_EXTERNAL ( attr ) )
return heap_tuple_fetch_attr ( attr ) ;
/* copy datum verbatim */
/*
* Copy into the caller ' s memory context , in case caller tries to
* pfree the result .
*/
result = ( struct varlena * ) palloc ( VARSIZE_ANY ( attr ) ) ;
memcpy ( result , attr , VARSIZE_ANY ( attr ) ) ;
}
@ -144,7 +146,10 @@ heap_tuple_fetch_attr(struct varlena * attr)
* heap_tuple_untoast_attr -
*
* Public entry point to get back a toasted value from compression
* or external storage .
* or external storage . The result is always non - extended varlena form .
*
* Note some callers assume that if the input is an EXTERNAL or COMPRESSED
* datum , the result will be a pfree ' able chunk .
* - - - - - - - - - -
*/
struct varlena *
@ -160,12 +165,16 @@ heap_tuple_untoast_attr(struct varlena * attr)
if ( VARATT_IS_COMPRESSED ( attr ) )
{
struct varlena * tmp = attr ;
attr = toast_decompress_datum ( tmp ) ;
pfree ( tmp ) ;
}
}
else if ( VARATT_IS_EXTERNAL_INDIRECT ( attr ) )
{
/*
* This is an indirect pointer - - - dereference it
*/
struct varatt_indirect redirect ;
VARATT_EXTERNAL_GET_POINTER ( redirect , attr ) ;
@ -174,7 +183,18 @@ heap_tuple_untoast_attr(struct varlena * attr)
/* nested indirect Datums aren't allowed */
Assert ( ! VARATT_IS_EXTERNAL_INDIRECT ( attr ) ) ;
/* recurse in case value is still extended in some other way */
attr = heap_tuple_untoast_attr ( attr ) ;
/* if it isn't, we'd better copy it */
if ( attr = = ( struct varlena * ) redirect . pointer )
{
struct varlena * result ;
result = ( struct varlena * ) palloc ( VARSIZE_ANY ( attr ) ) ;
memcpy ( result , attr , VARSIZE_ANY ( attr ) ) ;
attr = result ;
}
}
else if ( VARATT_IS_COMPRESSED ( attr ) )
{
@ -246,9 +266,12 @@ heap_tuple_untoast_attr_slice(struct varlena * attr,
else
preslice = attr ;
Assert ( ! VARATT_IS_EXTERNAL ( preslice ) ) ;
if ( VARATT_IS_COMPRESSED ( preslice ) )
{
struct varlena * tmp = preslice ;
preslice = toast_decompress_datum ( tmp ) ;
if ( tmp ! = attr )
@ -448,8 +471,6 @@ toast_delete(Relation rel, HeapTuple oldtup)
continue ;
else if ( VARATT_IS_EXTERNAL_ONDISK ( PointerGetDatum ( value ) ) )
toast_delete_datum ( rel , value ) ;
else if ( VARATT_IS_EXTERNAL_INDIRECT ( PointerGetDatum ( value ) ) )
elog ( ERROR , " attempt to delete tuple containing indirect datums " ) ;
}
}
}
@ -611,7 +632,8 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup,
/*
* We took care of UPDATE above , so any external value we find
* still in the tuple must be someone else ' s we cannot reuse .
* still in the tuple must be someone else ' s that we cannot reuse
* ( this includes the case of an out - of - line in - memory datum ) .
* Fetch it back ( without decompression , unless we are forcing
* PLAIN storage ) . If necessary , we ' ll push it out as a new
* external value below .
@ -1043,7 +1065,7 @@ toast_flatten_tuple(HeapTuple tup, TupleDesc tupleDesc)
new_value = ( struct varlena * ) DatumGetPointer ( toast_values [ i ] ) ;
if ( VARATT_IS_EXTERNAL ( new_value ) )
{
new_value = toast_fetch_datum ( new_value ) ;
new_value = heap_tuple_fetch_attr ( new_value ) ;
toast_values [ i ] = PointerGetDatum ( new_value ) ;
toast_free [ i ] = true ;
}
@ -1746,8 +1768,8 @@ toast_fetch_datum(struct varlena * attr)
int num_indexes ;
int validIndex ;
if ( VARATT_IS_EXTERNAL_INDIRECT ( attr ) )
elog ( ERROR , " shouldn't be called for indirect tuple s" ) ;
if ( ! VARATT_IS_EXTERNAL_ONDISK ( attr ) )
elog ( ERROR , " toast_fetch_datum shouldn't be called for non-ondisk datum s" ) ;
/* Must copy to access aligned fields */
VARATT_EXTERNAL_GET_POINTER ( toast_pointer , attr ) ;
@ -1923,7 +1945,8 @@ toast_fetch_datum_slice(struct varlena * attr, int32 sliceoffset, int32 length)
int num_indexes ;
int validIndex ;
Assert ( VARATT_IS_EXTERNAL_ONDISK ( attr ) ) ;
if ( ! VARATT_IS_EXTERNAL_ONDISK ( attr ) )
elog ( ERROR , " toast_fetch_datum_slice shouldn't be called for non-ondisk datums " ) ;
/* Must copy to access aligned fields */
VARATT_EXTERNAL_GET_POINTER ( toast_pointer , attr ) ;