aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJan Wieck <JanWieck@Yahoo.com>2000-07-21 10:31:31 +0000
committerJan Wieck <JanWieck@Yahoo.com>2000-07-21 10:31:31 +0000
commit82f3945a671aca50f63e87f7395d5948a2489e7b (patch)
tree300d84aab8fbb651b1c85245faf4e5269322a923 /src
parent9e85183bfc31c05bec81585ee43a27b6402a5c02 (diff)
downloadpostgresql-82f3945a671aca50f63e87f7395d5948a2489e7b.tar.gz
postgresql-82f3945a671aca50f63e87f7395d5948a2489e7b.zip
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
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/heap/heapam.c43
-rw-r--r--src/backend/access/heap/tuptoaster.c150
-rw-r--r--src/include/access/tuptoaster.h16
3 files changed, 202 insertions, 7 deletions
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 6a7f9ee1e2c..16d2ed470eb 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -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;
}
diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c
index 8abadaa7355..b1cd2601f99 100644
--- a/src/backend/access/heap/tuptoaster.c
+++ b/src/backend/access/heap/tuptoaster.c
@@ -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
diff --git a/src/include/access/tuptoaster.h b/src/include/access/tuptoaster.h
index da38f65385c..a84df07c686 100644
--- a/src/include/access/tuptoaster.h
+++ b/src/include/access/tuptoaster.h
@@ -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);