mirror of
https://github.com/postgres/postgres.git
synced 2025-07-24 14:22:24 +03:00
Add an extra header byte to TOAST-pointer datums to represent their size
explicitly. This means a TOAST pointer takes 18 bytes instead of 17 --- still smaller than in 8.2 --- which seems a good tradeoff to ensure we won't have painted ourselves into a corner if we want to support multiple types of TOAST pointer later on. Per discussion with Greg Stark.
This commit is contained in:
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.75 2007/09/26 23:29:10 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.76 2007/09/30 19:54:58 tgl Exp $
|
||||
*
|
||||
*
|
||||
* INTERFACE ROUTINES
|
||||
@ -52,6 +52,21 @@
|
||||
#define VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer) \
|
||||
((toast_pointer).va_extsize < (toast_pointer).va_rawsize - VARHDRSZ)
|
||||
|
||||
/*
|
||||
* Macro to fetch the possibly-unaligned contents of an EXTERNAL datum
|
||||
* into a local "struct varatt_external" toast pointer. This should be
|
||||
* just a memcpy, but some versions of gcc seem to produce broken code
|
||||
* that assumes the datum contents are aligned. Introducing an explicit
|
||||
* intermediate "varattrib_1b_e *" variable seems to fix it.
|
||||
*/
|
||||
#define VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr) \
|
||||
do { \
|
||||
varattrib_1b_e *attre = (varattrib_1b_e *) (attr); \
|
||||
Assert(VARSIZE_ANY_EXHDR(attre) == sizeof(toast_pointer)); \
|
||||
memcpy(&(toast_pointer), VARDATA_EXTERNAL(attre), sizeof(toast_pointer)); \
|
||||
} while (0)
|
||||
|
||||
|
||||
static void toast_delete_datum(Relation rel, Datum value);
|
||||
static Datum toast_save_datum(Relation rel, Datum value,
|
||||
bool use_wal, bool use_fsm);
|
||||
@ -172,7 +187,7 @@ heap_tuple_untoast_attr_slice(struct varlena *attr,
|
||||
{
|
||||
struct varatt_external toast_pointer;
|
||||
|
||||
memcpy(&toast_pointer, VARDATA_SHORT(attr), sizeof(toast_pointer));
|
||||
VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
|
||||
|
||||
/* fast path for non-compressed external datums */
|
||||
if (!VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer))
|
||||
@ -249,7 +264,7 @@ toast_raw_datum_size(Datum value)
|
||||
/* va_rawsize is the size of the original datum -- including header */
|
||||
struct varatt_external toast_pointer;
|
||||
|
||||
memcpy(&toast_pointer, VARDATA_SHORT(attr), sizeof(toast_pointer));
|
||||
VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
|
||||
result = toast_pointer.va_rawsize;
|
||||
}
|
||||
else if (VARATT_IS_COMPRESSED(attr))
|
||||
@ -294,7 +309,7 @@ toast_datum_size(Datum value)
|
||||
*/
|
||||
struct varatt_external toast_pointer;
|
||||
|
||||
memcpy(&toast_pointer, VARDATA_SHORT(attr), sizeof(toast_pointer));
|
||||
VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
|
||||
result = toast_pointer.va_extsize;
|
||||
}
|
||||
else if (VARATT_IS_SHORT(attr))
|
||||
@ -470,9 +485,8 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup,
|
||||
VARATT_IS_EXTERNAL(old_value))
|
||||
{
|
||||
if (toast_isnull[i] || !VARATT_IS_EXTERNAL(new_value) ||
|
||||
memcmp(VARDATA_SHORT(old_value),
|
||||
VARDATA_SHORT(new_value),
|
||||
sizeof(struct varatt_external)) != 0)
|
||||
memcmp((char *) old_value, (char *) new_value,
|
||||
VARSIZE_EXTERNAL(old_value)) != 0)
|
||||
{
|
||||
/*
|
||||
* The old external stored value isn't needed any more
|
||||
@ -1071,7 +1085,7 @@ toast_save_datum(Relation rel, Datum value,
|
||||
Datum t_values[3];
|
||||
bool t_isnull[3];
|
||||
CommandId mycid = GetCurrentCommandId();
|
||||
struct varlena *result;
|
||||
varattrib_pointer *result;
|
||||
struct varatt_external toast_pointer;
|
||||
struct
|
||||
{
|
||||
@ -1192,9 +1206,9 @@ toast_save_datum(Relation rel, Datum value,
|
||||
/*
|
||||
* Create the TOAST pointer value that we'll return
|
||||
*/
|
||||
result = (struct varlena *) palloc(sizeof(varattrib_pointer));
|
||||
SET_VARSIZE_EXTERNAL(result);
|
||||
memcpy(VARDATA_SHORT(result), &toast_pointer, sizeof(toast_pointer));
|
||||
result = (varattrib_pointer *) palloc(sizeof(varattrib_pointer));
|
||||
SET_VARSIZE_EXTERNAL(result, sizeof(varattrib_pointer));
|
||||
memcpy(VARDATA_EXTERNAL(result), &toast_pointer, sizeof(toast_pointer));
|
||||
|
||||
return PointerGetDatum(result);
|
||||
}
|
||||
@ -1221,8 +1235,7 @@ toast_delete_datum(Relation rel, Datum value)
|
||||
return;
|
||||
|
||||
/* Must copy to access aligned fields */
|
||||
memcpy(&toast_pointer, VARDATA_SHORT(attr),
|
||||
sizeof(struct varatt_external));
|
||||
VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
|
||||
|
||||
/*
|
||||
* Open the toast relation and its index
|
||||
@ -1289,8 +1302,7 @@ toast_fetch_datum(struct varlena *attr)
|
||||
int32 chunksize;
|
||||
|
||||
/* Must copy to access aligned fields */
|
||||
memcpy(&toast_pointer, VARDATA_SHORT(attr),
|
||||
sizeof(struct varatt_external));
|
||||
VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
|
||||
|
||||
ressize = toast_pointer.va_extsize;
|
||||
numchunks = ((ressize - 1) / TOAST_MAX_CHUNK_SIZE) + 1;
|
||||
@ -1452,8 +1464,7 @@ toast_fetch_datum_slice(struct varlena *attr, int32 sliceoffset, int32 length)
|
||||
Assert(VARATT_IS_EXTERNAL(attr));
|
||||
|
||||
/* Must copy to access aligned fields */
|
||||
memcpy(&toast_pointer, VARDATA_SHORT(attr),
|
||||
sizeof(struct varatt_external));
|
||||
VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
|
||||
|
||||
/*
|
||||
* It's nonsense to fetch slices of a compressed datum -- this isn't lo_*
|
||||
|
Reference in New Issue
Block a user