88 * Portions Copyright (c) 1994, Regents of the University of California
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/access/gist/gist.c,v 1.135 2006/05/17 16:34:59 teodor Exp $
11+ * $PostgreSQL: pgsql/src/backend/access/gist/gist.c,v 1.136 2006/05/19 16:15:17 teodor Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -936,31 +936,6 @@ gistmakedeal(GISTInsertState *state, GISTSTATE *giststate)
936936 gistxlogInsertCompletion (state -> r -> rd_node , & (state -> key ), 1 );
937937}
938938
939- static void
940- gistToRealOffset (OffsetNumber * arr , int len , OffsetNumber * reasloffset )
941- {
942- int i ;
943-
944- for (i = 0 ; i < len ; i ++ )
945- arr [i ] = reasloffset [arr [i ]];
946- }
947-
948- static IndexTupleData *
949- gistfillitupvec (IndexTuple * vec , int veclen , int * memlen ) {
950- char * ptr , * ret = palloc (BLCKSZ );
951- int i ;
952-
953- ptr = ret ;
954- for (i = 0 ; i < veclen ; i ++ ) {
955- memcpy (ptr , vec [i ], IndexTupleSize (vec [i ]));
956- ptr += IndexTupleSize (vec [i ]);
957- }
958-
959- * memlen = ptr - ret ;
960- Assert ( * memlen < BLCKSZ );
961- return (IndexTupleData * )ret ;
962- }
963-
964939/*
965940 * gistSplit -- split a page in the tree.
966941 */
@@ -975,100 +950,70 @@ gistSplit(Relation r,
975950 * rvectup ;
976951 GIST_SPLITVEC v ;
977952 GistEntryVector * entryvec ;
978- int i ,
979- fakeoffset ;
980- OffsetNumber * realoffset ;
981- IndexTuple * cleaneditup = itup ;
982- int lencleaneditup = len ;
953+ int i ;
954+ OffsetNumber offInvTuples [ MaxOffsetNumber ];
955+ int nOffInvTuples = 0 ;
983956 SplitedPageLayout * res = NULL ;
984957
985958 /* generate the item array */
986- realoffset = palloc ((len + 1 ) * sizeof (OffsetNumber ));
987959 entryvec = palloc (GEVHDRSZ + (len + 1 ) * sizeof (GISTENTRY ));
988960 entryvec -> n = len + 1 ;
989961
990- fakeoffset = FirstOffsetNumber ;
991962 for (i = 1 ; i <= len ; i ++ )
992963 {
993964 Datum datum ;
994965 bool IsNull ;
995966
996967 if (!GistPageIsLeaf (page ) && GistTupleIsInvalid (itup [i - 1 ]))
997- {
998- entryvec -> n -- ;
999968 /* remember position of invalid tuple */
1000- realoffset [entryvec -> n ] = i ;
1001- continue ;
1002- }
969+ offInvTuples [ nOffInvTuples ++ ] = i ;
970+
971+ if ( nOffInvTuples > 0 )
972+ /* we can safely do not decompress other keys, because
973+ we will do splecial processing, but
974+ it's needed to find another invalid tuples */
975+ continue ;
1003976
1004977 datum = index_getattr (itup [i - 1 ], 1 , giststate -> tupdesc , & IsNull );
1005- gistdentryinit (giststate , 0 , & (entryvec -> vector [fakeoffset ]),
978+ gistdentryinit (giststate , 0 , & (entryvec -> vector [i ]),
1006979 datum , r , page , i ,
1007980 ATTSIZE (datum , giststate -> tupdesc , 1 , IsNull ),
1008981 FALSE, IsNull );
1009- realoffset [fakeoffset ] = i ;
1010- fakeoffset ++ ;
1011982 }
1012983
1013984 /*
1014- * if it was invalid tuple then we need special processing. If it's
1015- * possible, we move all invalid tuples on right page. We should remember,
1016- * that union with invalid tuples is a invalid tuple.
985+ * if it was invalid tuple then we need special processing.
986+ * We move all invalid tuples on right page.
987+ *
988+ * if there is no place on left page, gistSplit will be called one more
989+ * time for left page.
990+ *
991+ * Normally, we never exec this code, but after crash replay it's possible
992+ * to get 'invalid' tuples (probability is low enough)
1017993 */
1018- if (entryvec -> n != len + 1 )
994+ if (nOffInvTuples > 0 )
1019995 {
1020- lencleaneditup = entryvec -> n - 1 ;
1021- cleaneditup = (IndexTuple * ) palloc (lencleaneditup * sizeof (IndexTuple ));
1022- for (i = 1 ; i < entryvec -> n ; i ++ )
1023- cleaneditup [i - 1 ] = itup [realoffset [i ] - 1 ];
1024-
1025- if (!gistfitpage (cleaneditup , lencleaneditup ))
1026- {
1027- /* no space on left to put all good tuples, so picksplit */
1028- gistUserPicksplit (r , entryvec , & v , cleaneditup , lencleaneditup , giststate );
1029- v .spl_leftvalid = true;
1030- v .spl_rightvalid = false;
1031- gistToRealOffset (v .spl_left , v .spl_nleft , realoffset );
1032- gistToRealOffset (v .spl_right , v .spl_nright , realoffset );
1033- }
1034- else
1035- {
1036- /* we can try to store all valid tuples on one page */
1037- v .spl_right = (OffsetNumber * ) palloc (entryvec -> n * sizeof (OffsetNumber ));
1038- v .spl_left = (OffsetNumber * ) palloc (entryvec -> n * sizeof (OffsetNumber ));
1039-
1040- if (lencleaneditup == 0 )
1041- {
1042- /* all tuples are invalid, so moves half of its to right */
1043- v .spl_leftvalid = v .spl_rightvalid = false;
1044- v .spl_nright = 0 ;
1045- v .spl_nleft = 0 ;
1046- for (i = 1 ; i <= len ; i ++ )
1047- if (i - 1 < len / 2 )
1048- v .spl_left [v .spl_nleft ++ ] = i ;
1049- else
1050- v .spl_right [v .spl_nright ++ ] = i ;
1051- }
1052- else
1053- {
1054- /*
1055- * we will not call gistUserPicksplit, just put good tuples on
1056- * left and invalid on right
1057- */
1058- v .spl_nleft = lencleaneditup ;
1059- v .spl_nright = 0 ;
1060- for (i = 1 ; i < entryvec -> n ; i ++ )
1061- v .spl_left [i - 1 ] = i ;
1062- gistToRealOffset (v .spl_left , v .spl_nleft , realoffset );
1063- v .spl_lattr [0 ] = v .spl_ldatum = (Datum ) 0 ;
1064- v .spl_rattr [0 ] = v .spl_rdatum = (Datum ) 0 ;
1065- v .spl_lisnull [0 ] = true;
1066- v .spl_risnull [0 ] = true;
1067- gistunionsubkey (r , giststate , itup , & v , true);
1068- v .spl_leftvalid = true;
1069- v .spl_rightvalid = false;
1070- }
1071- }
996+ GistSplitVec gsvp ;
997+
998+ v .spl_right = offInvTuples ;
999+ v .spl_nright = nOffInvTuples ;
1000+ v .spl_rightvalid = false;
1001+
1002+ v .spl_left = (OffsetNumber * ) palloc (entryvec -> n * sizeof (OffsetNumber ));
1003+ v .spl_nleft = 0 ;
1004+ for (i = 1 ; i <= len ; i ++ )
1005+ if ( !GistTupleIsInvalid (itup [i - 1 ]) )
1006+ v .spl_left [ v .spl_nleft ++ ] = i ;
1007+ v .spl_leftvalid = true;
1008+
1009+ gsvp .idgrp = NULL ;
1010+ gsvp .attrsize = v .spl_lattrsize ;
1011+ gsvp .attr = v .spl_lattr ;
1012+ gsvp .len = v .spl_nleft ;
1013+ gsvp .entries = v .spl_left ;
1014+ gsvp .isnull = v .spl_lisnull ;
1015+
1016+ gistunionsubkeyvec (giststate , itup , & gsvp , true);
10721017 }
10731018 else
10741019 {
@@ -1088,12 +1033,6 @@ gistSplit(Relation r,
10881033 for (i = 0 ; i < v .spl_nright ; i ++ )
10891034 rvectup [i ] = itup [v .spl_right [i ] - 1 ];
10901035
1091- /* place invalid tuples on right page if itsn't done yet */
1092- for (fakeoffset = entryvec -> n ; fakeoffset < len + 1 && lencleaneditup ; fakeoffset ++ )
1093- {
1094- rvectup [v .spl_nright ++ ] = itup [realoffset [fakeoffset ] - 1 ];
1095- }
1096-
10971036 /* finalyze splitting (may need another split) */
10981037 if (!gistfitpage (rvectup , v .spl_nright ))
10991038 {
0 commit comments