]> granicus.if.org Git - postgresql/commitdiff
Make sure the btree patch gets into 2.0 as well...
authorMarc G. Fournier <scrappy@hub.org>
Fri, 25 Oct 1996 09:55:36 +0000 (09:55 +0000)
committerMarc G. Fournier <scrappy@hub.org>
Fri, 25 Oct 1996 09:55:36 +0000 (09:55 +0000)
Still submitted by:  Massimo Dal Zotto <dz@cs.unitn.it>

src/backend/access/nbtree/nbtinsert.c

index b98733c123180be94139d6e43f0455e998c0925a..ebfa65f16d10cf79910c0b7a04863b7fbc0c4158 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.3 1996/10/23 07:39:00 scrappy Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.4 1996/10/25 09:55:36 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -815,7 +815,8 @@ _bt_itemcmp(Relation rel,
 
 /*
  *     _bt_updateitem() -- updates the key of the item identified by the
- *                         oid with the key of newItem (done in place)
+ *                         oid with the key of newItem (done in place if
+ *                         possible)
  *
  */
 static void
@@ -829,14 +830,17 @@ _bt_updateitem(Relation rel,
     OffsetNumber maxoff;
     OffsetNumber i;
     ItemPointerData itemPtrData;
-    BTItem item;
+    BTItem item, itemCopy;
     IndexTuple oldIndexTuple, newIndexTuple;
+    int newSize, oldSize, first;
     
     page = BufferGetPage(buf);
     maxoff = PageGetMaxOffsetNumber(page);
     
     /* locate item on the page */
-    i = P_HIKEY;
+    first = P_RIGHTMOST((BTPageOpaque) PageGetSpecialPointer(page)) \
+        ? P_HIKEY : P_FIRSTKEY;
+    i = first;
     do {
        item = (BTItem) PageGetItem(page, PageGetItemId(page, i));
        i = OffsetNumberNext(i);
@@ -849,9 +853,46 @@ _bt_updateitem(Relation rel,
     
     oldIndexTuple = &(item->bti_itup);
     newIndexTuple = &(newItem->bti_itup);
-    
-    /* keep the original item pointer */
-    ItemPointerCopy(&(oldIndexTuple->t_tid), &itemPtrData);
-    CopyIndexTuple(newIndexTuple, &oldIndexTuple);
-    ItemPointerCopy(&itemPtrData, &(oldIndexTuple->t_tid));
+    oldSize = DOUBLEALIGN(IndexTupleSize(oldIndexTuple));
+    newSize = DOUBLEALIGN(IndexTupleSize(newIndexTuple));
+#ifdef NBTINSERT_PATCH_DEBUG
+    printf("_bt_updateitem: newSize=%d, oldSize=%d\n", newSize, oldSize);
+#endif    
+
+    /*
+     * If new and old item have the same size do the update in place
+     * and return.
+     */ 
+    if (oldSize == newSize) {
+       /* keep the original item pointer */
+       ItemPointerCopy(&(oldIndexTuple->t_tid), &itemPtrData);
+       CopyIndexTuple(newIndexTuple, &oldIndexTuple);
+       ItemPointerCopy(&itemPtrData, &(oldIndexTuple->t_tid));
+       return;
+    }
+
+    /* 
+     * If new and old items have different size the update in place
+     * is not possible. In this case the old item is deleted and the
+     * new one is inserted.
+     * The new insertion should be done using _bt_insertonpg which
+     * would also takes care of the page splitting if needed, but
+     * unfortunately it doesn't work, so PageAddItem is used instead.
+     * There is the possibility that there is not enough space in the
+     * page and the item is not inserted.
+     */
+    itemCopy = palloc(newSize);
+    memmove((char *) itemCopy, (char *) newItem, newSize);
+    itemCopy->bti_oid = item->bti_oid;
+    newIndexTuple = &(itemCopy->bti_itup);
+    ItemPointerCopy(&(oldIndexTuple->t_tid), &(newIndexTuple->t_tid));
+
+    /*
+     * Get the offset number of the item then delete it and insert
+     * the new item in the same place.
+     */
+    i = OffsetNumberPrev(i);
+    PageIndexTupleDelete(page, i);
+    PageAddItem(page, (Item) itemCopy, newSize, i, LP_USED);
+    pfree(itemCopy);
 }