8
8
* Portions Copyright (c) 1994, Regents of the University of California
9
9
*
10
10
* 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 $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -936,31 +936,6 @@ gistmakedeal(GISTInsertState *state, GISTSTATE *giststate)
936
936
gistxlogInsertCompletion (state -> r -> rd_node ,& (state -> key ),1 );
937
937
}
938
938
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
-
964
939
/*
965
940
*gistSplit -- split a page in the tree.
966
941
*/
@@ -975,100 +950,70 @@ gistSplit(Relation r,
975
950
* rvectup ;
976
951
GIST_SPLITVEC v ;
977
952
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 ;
983
956
SplitedPageLayout * res = NULL ;
984
957
985
958
/* generate the item array */
986
- realoffset = palloc ((len + 1 )* sizeof (OffsetNumber ));
987
959
entryvec = palloc (GEVHDRSZ + (len + 1 )* sizeof (GISTENTRY ));
988
960
entryvec -> n = len + 1 ;
989
961
990
- fakeoffset = FirstOffsetNumber ;
991
962
for (i = 1 ;i <=len ;i ++ )
992
963
{
993
964
Datum datum ;
994
965
bool IsNull ;
995
966
996
967
if (!GistPageIsLeaf (page )&& GistTupleIsInvalid (itup [i - 1 ]))
997
- {
998
- entryvec -> n -- ;
999
968
/* 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 ;
1003
976
1004
977
datum = index_getattr (itup [i - 1 ],1 ,giststate -> tupdesc ,& IsNull );
1005
- gistdentryinit (giststate ,0 ,& (entryvec -> vector [fakeoffset ]),
978
+ gistdentryinit (giststate ,0 ,& (entryvec -> vector [i ]),
1006
979
datum ,r ,page ,i ,
1007
980
ATTSIZE (datum ,giststate -> tupdesc ,1 ,IsNull ),
1008
981
FALSE,IsNull );
1009
- realoffset [fakeoffset ]= i ;
1010
- fakeoffset ++ ;
1011
982
}
1012
983
1013
984
/*
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)
1017
993
*/
1018
- if (entryvec -> n != len + 1 )
994
+ if (nOffInvTuples > 0 )
1019
995
{
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);
1072
1017
}
1073
1018
else
1074
1019
{
@@ -1088,12 +1033,6 @@ gistSplit(Relation r,
1088
1033
for (i = 0 ;i < v .spl_nright ;i ++ )
1089
1034
rvectup [i ]= itup [v .spl_right [i ]- 1 ];
1090
1035
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
-
1097
1036
/* finalyze splitting (may need another split) */
1098
1037
if (!gistfitpage (rvectup ,v .spl_nright ))
1099
1038
{