77 *
88 *
99 * IDENTIFICATION
10- * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.1.1.1 1996/07/09 06:21:12 scrappy Exp $
10+ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.1.1.1.2.1 1996/10/25 09:53:32 scrappy Exp $
1111 *
1212 *-------------------------------------------------------------------------
1313 */
@@ -789,7 +789,8 @@ _bt_itemcmp(Relation rel,
789789
790790/*
791791 * _bt_updateitem() -- updates the key of the item identified by the
792- * oid with the key of newItem (done in place)
792+ * oid with the key of newItem (done in place if
793+ * possible)
793794 *
794795 */
795796static void
@@ -803,14 +804,17 @@ _bt_updateitem(Relation rel,
803804 OffsetNumber maxoff ;
804805 OffsetNumber i ;
805806 ItemPointerData itemPtrData ;
806- BTItem item ;
807+ BTItem item , itemCopy ;
807808 IndexTuple oldIndexTuple , newIndexTuple ;
809+ int newSize , oldSize , first ;
808810
809811 page = BufferGetPage (buf );
810812 maxoff = PageGetMaxOffsetNumber (page );
811813
812814 /* locate item on the page */
813- i = P_HIKEY ;
815+ first = P_RIGHTMOST ((BTPageOpaque ) PageGetSpecialPointer (page )) \
816+ ? P_HIKEY : P_FIRSTKEY ;
817+ i = first ;
814818 do {
815819 item = (BTItem ) PageGetItem (page , PageGetItemId (page , i ));
816820 i = OffsetNumberNext (i );
@@ -823,9 +827,46 @@ _bt_updateitem(Relation rel,
823827
824828 oldIndexTuple = & (item -> bti_itup );
825829 newIndexTuple = & (newItem -> bti_itup );
826-
827- /* keep the original item pointer */
828- ItemPointerCopy (& (oldIndexTuple -> t_tid ), & itemPtrData );
829- CopyIndexTuple (newIndexTuple , & oldIndexTuple );
830- ItemPointerCopy (& itemPtrData , & (oldIndexTuple -> t_tid ));
830+ oldSize = DOUBLEALIGN (IndexTupleSize (oldIndexTuple ));
831+ newSize = DOUBLEALIGN (IndexTupleSize (newIndexTuple ));
832+ #ifdef NBTINSERT_PATCH_DEBUG
833+ printf ("_bt_updateitem: newSize=%d, oldSize=%d\n" , newSize , oldSize );
834+ #endif
835+
836+ /*
837+ * If new and old item have the same size do the update in place
838+ * and return.
839+ */
840+ if (oldSize == newSize ) {
841+ /* keep the original item pointer */
842+ ItemPointerCopy (& (oldIndexTuple -> t_tid ), & itemPtrData );
843+ CopyIndexTuple (newIndexTuple , & oldIndexTuple );
844+ ItemPointerCopy (& itemPtrData , & (oldIndexTuple -> t_tid ));
845+ return ;
846+ }
847+
848+ /*
849+ * If new and old items have different size the update in place
850+ * is not possible. In this case the old item is deleted and the
851+ * new one is inserted.
852+ * The new insertion should be done using _bt_insertonpg which
853+ * would also takes care of the page splitting if needed, but
854+ * unfortunately it doesn't work, so PageAddItem is used instead.
855+ * There is the possibility that there is not enough space in the
856+ * page and the item is not inserted.
857+ */
858+ itemCopy = palloc (newSize );
859+ memmove ((char * ) itemCopy , (char * ) newItem , newSize );
860+ itemCopy -> bti_oid = item -> bti_oid ;
861+ newIndexTuple = & (itemCopy -> bti_itup );
862+ ItemPointerCopy (& (oldIndexTuple -> t_tid ), & (newIndexTuple -> t_tid ));
863+
864+ /*
865+ * Get the offset number of the item then delete it and insert
866+ * the new item in the same place.
867+ */
868+ i = OffsetNumberPrev (i );
869+ PageIndexTupleDelete (page , i );
870+ PageAddItem (page , (Item ) itemCopy , newSize , i , LP_USED );
871+ pfree (itemCopy );
831872}
0 commit comments