77 *
88 *
99 * IDENTIFICATION
10- *$Header: /cvsroot/pgsql/contrib/rtree_gist/Attic/rtree_gist.c,v 1.4 2001/10/25 05:49:20 momjian Exp $
10+ *$Header: /cvsroot/pgsql/contrib/rtree_gist/Attic/rtree_gist.c,v 1.5 2002/05/28 15:24:53 tgl Exp $
1111 *
1212 *-------------------------------------------------------------------------
1313 */
@@ -161,6 +161,22 @@ gbox_penalty(PG_FUNCTION_ARGS)
161161PG_RETURN_POINTER (result );
162162}
163163
164+ typedef struct {
165+ BOX * key ;
166+ int pos ;
167+ }KBsort ;
168+
169+ static int
170+ compare_KB (const void * a ,const void * b ) {
171+ BOX * abox = ((KBsort * )a )-> key ;
172+ BOX * bbox = ((KBsort * )b )-> key ;
173+ float sa = (abox -> high .x - abox -> low .x )* (abox -> high .y - abox -> low .y );
174+ float sb = (bbox -> high .x - bbox -> low .x )* (bbox -> high .y - bbox -> low .y );
175+
176+ if (sa == sb )return 0 ;
177+ return (sa > sb ) ?1 :-1 ;
178+ }
179+
164180/*
165181** The GiST PickSplit method
166182** New linear algorithm, see 'New Linear Node Splitting Algorithm for R-tree',
@@ -201,26 +217,22 @@ gbox_picksplit(PG_FUNCTION_ARGS)
201217for (i = OffsetNumberNext (FirstOffsetNumber );i <=maxoff ;i = OffsetNumberNext (i ))
202218{
203219cur = DatumGetBoxP (((GISTENTRY * )VARDATA (entryvec ))[i ].key );
204- if (pageunion .high .x < cur -> high .x )
205- {
220+ if (allisequal == true&& (
221+ pageunion .high .x != cur -> high .x ||
222+ pageunion .high .y != cur -> high .y ||
223+ pageunion .low .x != cur -> low .x ||
224+ pageunion .low .y != cur -> low .y
225+ ) )
206226allisequal = false;
227+
228+ if (pageunion .high .x < cur -> high .x )
207229pageunion .high .x = cur -> high .x ;
208- }
209230if (pageunion .low .x > cur -> low .x )
210- {
211- allisequal = false;
212231pageunion .low .x = cur -> low .x ;
213- }
214232if (pageunion .high .y < cur -> high .y )
215- {
216- allisequal = false;
217233pageunion .high .y = cur -> high .y ;
218- }
219234if (pageunion .low .y > cur -> low .y )
220- {
221- allisequal = false;
222235pageunion .low .y = cur -> low .y ;
223- }
224236}
225237
226238nbytes = (maxoff + 2 )* sizeof (OffsetNumber );
@@ -264,7 +276,7 @@ gbox_picksplit(PG_FUNCTION_ARGS)
264276unionB = (BOX * )palloc (sizeof (BOX ));
265277unionT = (BOX * )palloc (sizeof (BOX ));
266278
267- #define ADDLIST (list ,unionD ,pos ) do { \
279+ #define ADDLIST (list ,unionD ,pos , num ) do { \
268280if ( pos ) { \
269281if ( unionD->high.x < cur->high.x ) unionD->high.x= cur->high.x; \
270282if ( unionD->low.x> cur->low.x ) unionD->low.x= cur->low.x; \
@@ -273,25 +285,58 @@ gbox_picksplit(PG_FUNCTION_ARGS)
273285} else { \
274286memcpy( (void*)unionD, (void*) cur, sizeof( BOX ) ); \
275287} \
276- list[pos] =i ; \
288+ list[pos] =num ; \
277289(pos)++; \
278290} while(0)
279291
280292for (i = FirstOffsetNumber ;i <=maxoff ;i = OffsetNumberNext (i ))
281293{
282294cur = DatumGetBoxP (((GISTENTRY * )VARDATA (entryvec ))[i ].key );
283295if (cur -> low .x - pageunion .low .x < pageunion .high .x - cur -> high .x )
284- ADDLIST (listL ,unionL ,posL );
296+ ADDLIST (listL ,unionL ,posL , i );
285297else
286- ADDLIST (listR ,unionR ,posR );
298+ ADDLIST (listR ,unionR ,posR , i );
287299if (cur -> low .y - pageunion .low .y < pageunion .high .y - cur -> high .y )
288- ADDLIST (listB ,unionB ,posB );
300+ ADDLIST (listB ,unionB ,posB , i );
289301else
290- ADDLIST (listT ,unionT ,posT );
302+ ADDLIST (listT ,unionT ,posT , i );
291303}
292304
293- /* which split more optimal? */
305+ /* bad disposition, sort by ascending and resplit */
306+ if ( (posR == 0 || posL == 0 )&& (posT == 0 || posB == 0 ) ) {
307+ KBsort * arr = (KBsort * )palloc (sizeof (KBsort )* maxoff );
308+ posL = posR = posB = posT = 0 ;
309+ for (i = FirstOffsetNumber ;i <=maxoff ;i = OffsetNumberNext (i )) {
310+ arr [i - 1 ].key = DatumGetBoxP (((GISTENTRY * )VARDATA (entryvec ))[i ].key );
311+ arr [i - 1 ].pos = i ;
312+ }
313+ qsort (arr ,maxoff ,sizeof (KBsort ),compare_KB );
314+ for (i = FirstOffsetNumber ;i <=maxoff ;i = OffsetNumberNext (i )) {
315+ cur = arr [i - 1 ].key ;
316+ if (cur -> low .x - pageunion .low .x < pageunion .high .x - cur -> high .x )
317+ ADDLIST (listL ,unionL ,posL ,arr [i - 1 ].pos );
318+ else if (cur -> low .x - pageunion .low .x == pageunion .high .x - cur -> high .x ) {
319+ if (posL > posR )
320+ ADDLIST (listR ,unionR ,posR ,arr [i - 1 ].pos );
321+ else
322+ ADDLIST (listL ,unionL ,posL ,arr [i - 1 ].pos );
323+ }else
324+ ADDLIST (listR ,unionR ,posR ,arr [i - 1 ].pos );
325+
326+ if (cur -> low .y - pageunion .low .y < pageunion .high .y - cur -> high .y )
327+ ADDLIST (listB ,unionB ,posB ,arr [i - 1 ].pos );
328+ else if (cur -> low .y - pageunion .low .y == pageunion .high .y - cur -> high .y ) {
329+ if (posB > posT )
330+ ADDLIST (listT ,unionT ,posT ,arr [i - 1 ].pos );
331+ else
332+ ADDLIST (listB ,unionB ,posB ,arr [i - 1 ].pos );
333+ }else
334+ ADDLIST (listT ,unionT ,posT ,arr [i - 1 ].pos );
335+ }
336+ pfree (arr );
337+ }
294338
339+ /* which split more optimal? */
295340if (Max (posL ,posR )< Max (posB ,posT ))
296341direction = 'x' ;
297342else if (Max (posL ,posR )> Max (posB ,posT ))