diff options
Diffstat (limited to 'src/backend/access/heap/tuptoaster.c')
-rw-r--r-- | src/backend/access/heap/tuptoaster.c | 150 |
1 files changed, 145 insertions, 5 deletions
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 |