]> granicus.if.org Git - postgresql/commitdiff
Temporary fix to make TOAST vacuum-safe. All values are forced to be
authorJan Wieck <JanWieck@Yahoo.com>
Fri, 21 Jul 2000 10:31:31 +0000 (10:31 +0000)
committerJan Wieck <JanWieck@Yahoo.com>
Fri, 21 Jul 2000 10:31:31 +0000 (10:31 +0000)
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
src/backend/access/heap/tuptoaster.c
src/include/access/tuptoaster.h

index 6a7f9ee1e2c609a9757f077433d8011c64b9feaa..16d2ed470eb60fdf7540dbb93c3097d4042ff4d3 100644 (file)
@@ -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;
 }
 
index 8abadaa7355eb5c75bbfed4ae9f071e47ef5af21..b1cd2601f99e587f3399762d04ff9e6d95a16f4a 100644 (file)
@@ -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
 
 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
index da38f65385c5865b617377ae925addc529aa2852..a84df07c68649f8c5f0b0d6b7e61f221882d6a76 100644 (file)
@@ -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 $
  *
  *-------------------------------------------------------------------------
  */
 #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(                                                                                               \
                                        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);