From 82f3945a671aca50f63e87f7395d5948a2489e7b Mon Sep 17 00:00:00 2001 From: Jan Wieck Date: Fri, 21 Jul 2000 10:31:31 +0000 Subject: [PATCH] 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 --- src/backend/access/heap/heapam.c | 43 +++++++++- src/backend/access/heap/tuptoaster.c | 150 +++++++++++++++++++++++++++++++++-- src/include/access/tuptoaster.h | 16 +++- 3 files changed, 202 insertions(+), 7 deletions(-) diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 6a7f9ee1e2..16d2ed470e 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 8abadaa735..b1cd2601f9 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 da38f65385..a84df07c68 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); -- 2.11.0