1
0
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:
Tom Lane
2007-09-30 19:54:58 +00:00
parent 3ff0018c2e
commit 27b8922221
4 changed files with 58 additions and 37 deletions

View File

@ -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_*