mirror of
https://github.com/postgres/postgres.git
synced 2025-04-27 22:56:53 +03:00
Temporary fix to make TOAST vacuum-safe. All values are forced to be
in memory (plain or compressed) in the tuple returned from the heap-am. So no index will ever contain an external reference. Jan
This commit is contained in:
parent
9e85183bfc
commit
82f3945a67
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.79 2000/07/04 17:11:40 wieck Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.80 2000/07/21 10:31:30 wieck Exp $
|
||||
*
|
||||
*
|
||||
* INTERFACE ROUTINES
|
||||
@ -1274,6 +1274,10 @@ Oid
|
||||
heap_insert(Relation relation, HeapTuple tup)
|
||||
{
|
||||
Buffer buffer;
|
||||
#ifndef TOAST_INDICES
|
||||
HeapTupleHeader plaintdata = NULL;
|
||||
int32 plaintlen = 0;
|
||||
#endif
|
||||
|
||||
/* increment access statistics */
|
||||
tup->tableOid = relation->rd_id;
|
||||
@ -1309,7 +1313,11 @@ heap_insert(Relation relation, HeapTuple tup)
|
||||
*/
|
||||
if (HeapTupleHasExtended(tup) ||
|
||||
(MAXALIGN(tup->t_len) > (MaxTupleSize / 4)))
|
||||
#ifdef TOAST_INDICES
|
||||
heap_tuple_toast_attrs(relation, tup, NULL);
|
||||
#else
|
||||
heap_tuple_toast_attrs(relation, tup, NULL, &plaintdata, &plaintlen);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Find buffer for this tuple */
|
||||
@ -1347,6 +1355,16 @@ heap_insert(Relation relation, HeapTuple tup)
|
||||
if (IsSystemRelationName(RelationGetRelationName(relation)))
|
||||
RelationMark4RollbackHeapTuple(relation, tup);
|
||||
|
||||
#ifndef TOAST_INDICES
|
||||
if (plaintdata != NULL && tup->t_data != plaintdata)
|
||||
{
|
||||
if (tup->t_datamcxt != NULL && (char *) (tup->t_data) !=
|
||||
((char *) tup + HEAPTUPLESIZE))
|
||||
pfree(tup->t_data);
|
||||
tup->t_data = plaintdata;
|
||||
tup->t_len = plaintlen;
|
||||
}
|
||||
#endif
|
||||
return tup->t_data->t_oid;
|
||||
}
|
||||
|
||||
@ -1461,7 +1479,11 @@ l1:
|
||||
* ----------
|
||||
*/
|
||||
if (HeapTupleHasExtended(&tp))
|
||||
#ifdef TOAST_INDICES
|
||||
heap_tuple_toast_attrs(relation, NULL, &(tp));
|
||||
#else
|
||||
heap_tuple_toast_attrs(relation, NULL, &(tp), NULL, NULL);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||
@ -1486,6 +1508,10 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
|
||||
PageHeader dp;
|
||||
Buffer buffer, newbuf;
|
||||
int result;
|
||||
#ifndef TOAST_INDICES
|
||||
HeapTupleHeader plaintdata = NULL;
|
||||
int32 plaintlen = 0;
|
||||
#endif
|
||||
|
||||
newtup->tableOid = relation->rd_id;
|
||||
/* increment access statistics */
|
||||
@ -1574,7 +1600,11 @@ l2:
|
||||
if (HeapTupleHasExtended(&oldtup) ||
|
||||
HeapTupleHasExtended(newtup) ||
|
||||
(MAXALIGN(newtup->t_len) > (MaxTupleSize / 4)))
|
||||
#ifdef TOAST_INDICES
|
||||
heap_tuple_toast_attrs(relation, newtup, &oldtup);
|
||||
#else
|
||||
heap_tuple_toast_attrs(relation, newtup, &oldtup, &plaintdata, &plaintlen);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Find buffer for new tuple */
|
||||
@ -1637,6 +1667,17 @@ l2:
|
||||
RelationInvalidateHeapTuple(relation, &oldtup);
|
||||
RelationMark4RollbackHeapTuple(relation, newtup);
|
||||
|
||||
#ifndef TOAST_INDICES
|
||||
if (plaintdata != NULL && newtup->t_data != plaintdata)
|
||||
{
|
||||
if (newtup->t_datamcxt != NULL && (char *) (newtup->t_data) !=
|
||||
((char *) newtup + HEAPTUPLESIZE))
|
||||
pfree(newtup->t_data);
|
||||
newtup->t_data = plaintdata;
|
||||
newtup->t_len = plaintlen;
|
||||
}
|
||||
#endif
|
||||
|
||||
return HeapTupleMayBeUpdated;
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.7 2000/07/11 12:32:03 wieck Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.8 2000/07/21 10:31:30 wieck Exp $
|
||||
*
|
||||
*
|
||||
* INTERFACE ROUTINES
|
||||
@ -43,8 +43,14 @@
|
||||
|
||||
static void toast_delete(Relation rel, HeapTuple oldtup);
|
||||
static void toast_delete_datum(Relation rel, Datum value);
|
||||
#ifdef TOAST_INDICES
|
||||
static void toast_insert_or_update(Relation rel, HeapTuple newtup,
|
||||
HeapTuple oldtup);
|
||||
#else
|
||||
static void toast_insert_or_update(Relation rel, HeapTuple newtup,
|
||||
HeapTuple oldtup, HeapTupleHeader *plaintdata,
|
||||
int32 *plaintlen);
|
||||
#endif
|
||||
static Datum toast_compress_datum(Datum value);
|
||||
static Datum toast_save_datum(Relation rel, Oid mainoid, int16 attno, Datum value);
|
||||
|
||||
@ -59,6 +65,7 @@ static varattrib *toast_fetch_datum(varattrib *attr);
|
||||
* Calls the appropriate event specific action.
|
||||
* ----------
|
||||
*/
|
||||
#ifdef TOAST_INDICES
|
||||
void
|
||||
heap_tuple_toast_attrs(Relation rel, HeapTuple newtup, HeapTuple oldtup)
|
||||
{
|
||||
@ -67,6 +74,17 @@ heap_tuple_toast_attrs(Relation rel, HeapTuple newtup, HeapTuple oldtup)
|
||||
else
|
||||
toast_insert_or_update(rel, newtup, oldtup);
|
||||
}
|
||||
#else
|
||||
void
|
||||
heap_tuple_toast_attrs(Relation rel, HeapTuple newtup,
|
||||
HeapTuple oldtup, HeapTupleHeader *plaintdata, int32 *plaintlen)
|
||||
{
|
||||
if (newtup == NULL)
|
||||
toast_delete(rel, oldtup);
|
||||
else
|
||||
toast_insert_or_update(rel, newtup, oldtup, plaintdata, plaintlen);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* ----------
|
||||
@ -181,7 +199,12 @@ toast_delete(Relation rel, HeapTuple oldtup)
|
||||
* ----------
|
||||
*/
|
||||
static void
|
||||
#ifdef TOAST_INDICES
|
||||
toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
|
||||
#else
|
||||
toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup,
|
||||
HeapTupleHeader *plaintdata, int32 *plaintlen)
|
||||
#endif
|
||||
{
|
||||
TupleDesc tupleDesc;
|
||||
Form_pg_attribute *att;
|
||||
@ -204,6 +227,12 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
|
||||
bool toast_free[MaxHeapAttributeNumber];
|
||||
bool toast_delold[MaxHeapAttributeNumber];
|
||||
|
||||
#ifndef TOAST_INDICES
|
||||
bool need_plain = false;
|
||||
Datum toast_plains[MaxHeapAttributeNumber];
|
||||
bool toast_freeplain[MaxHeapAttributeNumber];
|
||||
#endif
|
||||
|
||||
/* ----------
|
||||
* Get the tuple descriptor, the number of and attribute
|
||||
* descriptors and the location of the tuple values.
|
||||
@ -217,10 +246,11 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
|
||||
* Then collect information about the values given
|
||||
* ----------
|
||||
*/
|
||||
memset(toast_action, ' ', numAttrs * sizeof(char));
|
||||
memset(toast_nulls, ' ', numAttrs * sizeof(char));
|
||||
memset(toast_free, 0, numAttrs * sizeof(bool));
|
||||
memset(toast_delold, 0, numAttrs * sizeof(bool));
|
||||
memset(toast_action, ' ', numAttrs * sizeof(char));
|
||||
memset(toast_nulls, ' ', numAttrs * sizeof(char));
|
||||
memset(toast_free, 0, numAttrs * sizeof(bool));
|
||||
memset(toast_freeplain, 0, numAttrs * sizeof(bool));
|
||||
memset(toast_delold, 0, numAttrs * sizeof(bool));
|
||||
for (i = 0; i < numAttrs; i++)
|
||||
{
|
||||
varattrib *old_value;
|
||||
@ -270,6 +300,25 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
|
||||
*/
|
||||
toast_action[i] = 'p';
|
||||
toast_sizes[i] = VARATT_SIZE(toast_values[i]);
|
||||
|
||||
#ifndef TOAST_INDICES
|
||||
/* ----------
|
||||
* But the tuple returned by the heap-am
|
||||
* function must not contain external references.
|
||||
* So we have to construct another plain tuple
|
||||
* later.
|
||||
* ----------
|
||||
*/
|
||||
if (att[i]->attstorage == 'x' || att[i]->attstorage == 'm')
|
||||
toast_plains[i] = PointerGetDatum(
|
||||
toast_fetch_datum(new_value));
|
||||
else
|
||||
toast_plains[i] = PointerGetDatum(
|
||||
heap_tuple_untoast_attr(new_value));
|
||||
toast_freeplain[i] = true;
|
||||
need_plain = true;
|
||||
#endif
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -320,10 +369,17 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
|
||||
{
|
||||
toast_values[i] = PointerGetDatum(heap_tuple_untoast_attr(
|
||||
(varattrib *)DatumGetPointer(toast_values[i])));
|
||||
#ifndef TOAST_INDICES
|
||||
toast_plains[i] = toast_values[i];
|
||||
#endif
|
||||
toast_free[i] = true;
|
||||
need_change = true;
|
||||
need_free = true;
|
||||
}
|
||||
#ifndef TOAST_INDICES
|
||||
else
|
||||
toast_plains[i] = toast_values[i];
|
||||
#endif
|
||||
|
||||
/* ----------
|
||||
* Remember the size of this attribute
|
||||
@ -339,6 +395,9 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
|
||||
*/
|
||||
toast_action[i] = 'p';
|
||||
toast_sizes[i] = att[i]->attlen;
|
||||
#ifndef TOAST_INDICES
|
||||
toast_plains[i] = toast_values[i];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -397,6 +456,9 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
|
||||
old_value = toast_values[i];
|
||||
|
||||
toast_values[i] = toast_compress_datum(toast_values[i]);
|
||||
#ifndef TOAST_INDICES
|
||||
toast_plains[i] = toast_values[i];
|
||||
#endif
|
||||
|
||||
if (toast_free[i])
|
||||
pfree(DatumGetPointer(old_value));
|
||||
@ -454,8 +516,14 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
|
||||
newtup->t_data->t_oid,
|
||||
i + 1,
|
||||
toast_values[i]);
|
||||
#ifndef TOAST_INDICES
|
||||
need_plain = true;
|
||||
if (toast_free[i])
|
||||
toast_freeplain[i] = true;
|
||||
#else
|
||||
if (toast_free[i])
|
||||
pfree(DatumGetPointer(old_value));
|
||||
#endif
|
||||
|
||||
toast_free[i] = true;
|
||||
toast_sizes[i] = VARATT_SIZE(toast_values[i]);
|
||||
@ -506,6 +574,9 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
|
||||
old_value = toast_values[i];
|
||||
|
||||
toast_values[i] = toast_compress_datum(toast_values[i]);
|
||||
#ifndef TOAST_INDICES
|
||||
toast_plains[i] = toast_values[i];
|
||||
#endif
|
||||
|
||||
if (toast_free[i])
|
||||
pfree(DatumGetPointer(old_value));
|
||||
@ -562,8 +633,14 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
|
||||
newtup->t_data->t_oid,
|
||||
i + 1,
|
||||
toast_values[i]);
|
||||
#ifndef TOAST_INDICES
|
||||
need_plain = true;
|
||||
if (toast_free[i])
|
||||
toast_freeplain[i] = true;
|
||||
#else
|
||||
if (toast_free[i])
|
||||
pfree(DatumGetPointer(old_value));
|
||||
#endif
|
||||
|
||||
toast_free[i] = true;
|
||||
toast_sizes[i] = VARATT_SIZE(toast_values[i]);
|
||||
@ -637,14 +714,77 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
|
||||
}
|
||||
|
||||
|
||||
#ifndef TOAST_INDICES
|
||||
/* ----------
|
||||
* In the case we toasted any values, we need to build
|
||||
* a new heap tuple with the changed values.
|
||||
* ----------
|
||||
*/
|
||||
if (need_plain)
|
||||
{
|
||||
int32 new_len;
|
||||
MemoryContext oldcxt;
|
||||
|
||||
/* ----------
|
||||
* Calculate the new size of the tuple
|
||||
* ----------
|
||||
*/
|
||||
new_len = offsetof(HeapTupleHeaderData, t_bits);
|
||||
if (has_nulls)
|
||||
new_len += BITMAPLEN(numAttrs);
|
||||
new_len = MAXALIGN(new_len);
|
||||
new_len += ComputeDataSize(tupleDesc, toast_plains, toast_nulls);
|
||||
|
||||
/* ----------
|
||||
* Switch to the memory context of the HeapTuple structure
|
||||
* and allocate the new tuple.
|
||||
* ----------
|
||||
*/
|
||||
oldcxt = MemoryContextSwitchTo(newtup->t_datamcxt);
|
||||
*plaintdata = palloc(new_len);
|
||||
*plaintlen = new_len;
|
||||
|
||||
/* ----------
|
||||
* Put the tuple header and the changed values into place
|
||||
* ----------
|
||||
*/
|
||||
memcpy(*plaintdata, newtup->t_data, newtup->t_data->t_hoff);
|
||||
|
||||
DataFill((char *)(MAXALIGN((long)(*plaintdata) +
|
||||
offsetof(HeapTupleHeaderData, t_bits) +
|
||||
((has_nulls) ? BITMAPLEN(numAttrs) : 0))),
|
||||
tupleDesc,
|
||||
toast_plains,
|
||||
toast_nulls,
|
||||
&((*plaintdata)->t_infomask),
|
||||
has_nulls ? (*plaintdata)->t_bits : NULL);
|
||||
|
||||
/* ----------
|
||||
* Switch back to the old memory context
|
||||
* ----------
|
||||
*/
|
||||
MemoryContextSwitchTo(oldcxt);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* ----------
|
||||
* Free allocated temp values
|
||||
* ----------
|
||||
*/
|
||||
if (need_free)
|
||||
for (i = 0; i < numAttrs; i++)
|
||||
#ifndef TOAST_INDICES
|
||||
{
|
||||
if (toast_free[i])
|
||||
pfree(DatumGetPointer(toast_values[i]));
|
||||
if (toast_freeplain[i])
|
||||
pfree(DatumGetPointer(toast_plains[i]));
|
||||
}
|
||||
#else
|
||||
if (toast_free[i])
|
||||
pfree(DatumGetPointer(toast_values[i]));
|
||||
#endif
|
||||
|
||||
/* ----------
|
||||
* Delete external values from the old tuple
|
||||
|
@ -6,7 +6,7 @@
|
||||
*
|
||||
* Copyright (c) 2000, PostgreSQL Development Team
|
||||
*
|
||||
* $Id: tuptoaster.h,v 1.5 2000/07/04 06:11:50 tgl Exp $
|
||||
* $Id: tuptoaster.h,v 1.6 2000/07/21 10:31:31 wieck Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -20,6 +20,14 @@
|
||||
#include "access/tupmacs.h"
|
||||
#include "utils/rel.h"
|
||||
|
||||
/*
|
||||
* DO NOT ENABLE THIS
|
||||
* until we have crash safe file versioning and you've
|
||||
* changed VACUUM to recreate indices that use possibly
|
||||
* toasted values. 2000/07/20 Jan
|
||||
*/
|
||||
#undef TOAST_INDICES
|
||||
|
||||
|
||||
#define TOAST_MAX_CHUNK_SIZE ((MaxTupleSize - \
|
||||
MAXALIGN( \
|
||||
@ -29,8 +37,14 @@
|
||||
MAXALIGN(VARHDRSZ))) / 4)
|
||||
|
||||
|
||||
#ifdef TOAST_INDICES
|
||||
extern void heap_tuple_toast_attrs(Relation rel,
|
||||
HeapTuple newtup, HeapTuple oldtup);
|
||||
#else
|
||||
extern void heap_tuple_toast_attrs(Relation rel,
|
||||
HeapTuple newtup, HeapTuple oldtup,
|
||||
HeapTupleHeader *plaintdata, int32 *plaintlen);
|
||||
#endif
|
||||
|
||||
extern varattrib *heap_tuple_untoast_attr(varattrib * attr);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user