7
7
*
8
8
*
9
9
* 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 $
11
11
*
12
12
*-------------------------------------------------------------------------
13
13
*/
@@ -789,7 +789,8 @@ _bt_itemcmp(Relation rel,
789
789
790
790
/*
791
791
* _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)
793
794
*
794
795
*/
795
796
static void
@@ -803,14 +804,17 @@ _bt_updateitem(Relation rel,
803
804
OffsetNumber maxoff ;
804
805
OffsetNumber i ;
805
806
ItemPointerData itemPtrData ;
806
- BTItem item ;
807
+ BTItem item , itemCopy ;
807
808
IndexTuple oldIndexTuple , newIndexTuple ;
809
+ int newSize , oldSize , first ;
808
810
809
811
page = BufferGetPage (buf );
810
812
maxoff = PageGetMaxOffsetNumber (page );
811
813
812
814
/* locate item on the page */
813
- i = P_HIKEY ;
815
+ first = P_RIGHTMOST ((BTPageOpaque ) PageGetSpecialPointer (page )) \
816
+ ? P_HIKEY : P_FIRSTKEY ;
817
+ i = first ;
814
818
do {
815
819
item = (BTItem ) PageGetItem (page , PageGetItemId (page , i ));
816
820
i = OffsetNumberNext (i );
@@ -823,9 +827,46 @@ _bt_updateitem(Relation rel,
823
827
824
828
oldIndexTuple = & (item -> bti_itup );
825
829
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 );
831
872
}
0 commit comments