7
7
*
8
8
*
9
9
* IDENTIFICATION
10
- * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.3 1996/10/23 07:39:00 scrappy Exp $
10
+ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.4 1996/10/25 09:55:36 scrappy Exp $
11
11
*
12
12
*-------------------------------------------------------------------------
13
13
*/
@@ -815,7 +815,8 @@ _bt_itemcmp(Relation rel,
815
815
816
816
/*
817
817
* _bt_updateitem() -- updates the key of the item identified by the
818
- * oid with the key of newItem (done in place)
818
+ * oid with the key of newItem (done in place if
819
+ * possible)
819
820
*
820
821
*/
821
822
static void
@@ -829,14 +830,17 @@ _bt_updateitem(Relation rel,
829
830
OffsetNumber maxoff ;
830
831
OffsetNumber i ;
831
832
ItemPointerData itemPtrData ;
832
- BTItem item ;
833
+ BTItem item , itemCopy ;
833
834
IndexTuple oldIndexTuple , newIndexTuple ;
835
+ int newSize , oldSize , first ;
834
836
835
837
page = BufferGetPage (buf );
836
838
maxoff = PageGetMaxOffsetNumber (page );
837
839
838
840
/* locate item on the page */
839
- i = P_HIKEY ;
841
+ first = P_RIGHTMOST ((BTPageOpaque ) PageGetSpecialPointer (page )) \
842
+ ? P_HIKEY : P_FIRSTKEY ;
843
+ i = first ;
840
844
do {
841
845
item = (BTItem ) PageGetItem (page , PageGetItemId (page , i ));
842
846
i = OffsetNumberNext (i );
@@ -849,9 +853,46 @@ _bt_updateitem(Relation rel,
849
853
850
854
oldIndexTuple = & (item -> bti_itup );
851
855
newIndexTuple = & (newItem -> bti_itup );
852
-
853
- /* keep the original item pointer */
854
- ItemPointerCopy (& (oldIndexTuple -> t_tid ), & itemPtrData );
855
- CopyIndexTuple (newIndexTuple , & oldIndexTuple );
856
- ItemPointerCopy (& itemPtrData , & (oldIndexTuple -> t_tid ));
856
+ oldSize = DOUBLEALIGN (IndexTupleSize (oldIndexTuple ));
857
+ newSize = DOUBLEALIGN (IndexTupleSize (newIndexTuple ));
858
+ #ifdef NBTINSERT_PATCH_DEBUG
859
+ printf ("_bt_updateitem: newSize=%d, oldSize=%d\n" , newSize , oldSize );
860
+ #endif
861
+
862
+ /*
863
+ * If new and old item have the same size do the update in place
864
+ * and return.
865
+ */
866
+ if (oldSize == newSize ) {
867
+ /* keep the original item pointer */
868
+ ItemPointerCopy (& (oldIndexTuple -> t_tid ), & itemPtrData );
869
+ CopyIndexTuple (newIndexTuple , & oldIndexTuple );
870
+ ItemPointerCopy (& itemPtrData , & (oldIndexTuple -> t_tid ));
871
+ return ;
872
+ }
873
+
874
+ /*
875
+ * If new and old items have different size the update in place
876
+ * is not possible. In this case the old item is deleted and the
877
+ * new one is inserted.
878
+ * The new insertion should be done using _bt_insertonpg which
879
+ * would also takes care of the page splitting if needed, but
880
+ * unfortunately it doesn't work, so PageAddItem is used instead.
881
+ * There is the possibility that there is not enough space in the
882
+ * page and the item is not inserted.
883
+ */
884
+ itemCopy = palloc (newSize );
885
+ memmove ((char * ) itemCopy , (char * ) newItem , newSize );
886
+ itemCopy -> bti_oid = item -> bti_oid ;
887
+ newIndexTuple = & (itemCopy -> bti_itup );
888
+ ItemPointerCopy (& (oldIndexTuple -> t_tid ), & (newIndexTuple -> t_tid ));
889
+
890
+ /*
891
+ * Get the offset number of the item then delete it and insert
892
+ * the new item in the same place.
893
+ */
894
+ i = OffsetNumberPrev (i );
895
+ PageIndexTupleDelete (page , i );
896
+ PageAddItem (page , (Item ) itemCopy , newSize , i , LP_USED );
897
+ pfree (itemCopy );
857
898
}
0 commit comments