diff -c -r -N src.orig/backend/access/gist/gistproc.c src/backend/access/gist/gistproc.c
*** src.orig/backend/access/gist/gistproc.c	2009-04-03 12:06:58.000000000 +0400
--- src/backend/access/gist/gistproc.c	2009-04-03 17:00:32.000000000 +0400
***************
*** 273,278 ****
--- 273,341 ----
  }
  
  /*
+  * Trivial split: half of entries will be placed on one page
+  * and another half - to another
+  */
+ static void
+ fallbackSplit(GistEntryVector *entryvec, GIST_SPLITVEC *v)
+ {
+ 	OffsetNumber	i, 
+ 					maxoff;
+ 	BOX			   *unionL = NULL,
+ 				   *unionR = NULL;
+ 	int				nbytes;
+ 
+ 	maxoff = entryvec->n - 1;
+ 
+ 	nbytes = (maxoff + 2) * sizeof(OffsetNumber);
+ 	v->spl_left = (OffsetNumber *) palloc(nbytes);
+ 	v->spl_right = (OffsetNumber *) palloc(nbytes);
+ 	v->spl_nleft = v->spl_nright = 0;
+ 
+ 	for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
+ 	{
+ 		BOX * cur = DatumGetBoxP(entryvec->vector[i].key);
+ 
+ 		if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
+ 		{
+ 			v->spl_left[v->spl_nleft] = i;
+ 			if (unionL == NULL)
+ 			{
+ 				unionL = (BOX *) palloc(sizeof(BOX));
+ 				*unionL = *cur;
+ 			}
+ 			else
+ 				adjustBox(unionL, cur);
+ 
+ 			v->spl_nleft++;
+ 		}
+ 		else
+ 		{
+ 			v->spl_right[v->spl_nright] = i;
+ 			if (unionR == NULL)
+ 			{
+ 				unionR = (BOX *) palloc(sizeof(BOX));
+ 				*unionR = *cur;
+ 			}
+ 			else
+ 				adjustBox(unionR, cur);
+ 
+ 			v->spl_nright++;
+ 		}
+ 	}
+ 
+ 	if (v->spl_ldatum_exists)
+ 		adjustBox(unionL, DatumGetBoxP(v->spl_ldatum));
+ 	v->spl_ldatum = BoxPGetDatum(unionL);
+ 
+ 	if (v->spl_rdatum_exists)
+ 		adjustBox(unionR, DatumGetBoxP(v->spl_rdatum));
+ 	v->spl_rdatum = BoxPGetDatum(unionR);
+ 
+ 	v->spl_ldatum_exists = v->spl_rdatum_exists = false;
+ }
+ 
+ /*
   * The GiST PickSplit method
   *
   * New linear algorithm, see 'New Linear Node Splitting Algorithm for R-tree',
***************
*** 324,375 ****
  		adjustBox(&pageunion, cur);
  	}
  
- 	nbytes = (maxoff + 2) * sizeof(OffsetNumber);
- 	listL = (OffsetNumber *) palloc(nbytes);
- 	listR = (OffsetNumber *) palloc(nbytes);
- 	unionL = (BOX *) palloc(sizeof(BOX));
- 	unionR = (BOX *) palloc(sizeof(BOX));
  	if (allisequal)
  	{
! 		cur = DatumGetBoxP(entryvec->vector[OffsetNumberNext(FirstOffsetNumber)].key);
! 		if (memcmp((void *) cur, (void *) &pageunion, sizeof(BOX)) == 0)
! 		{
! 			v->spl_left = listL;
! 			v->spl_right = listR;
! 			v->spl_nleft = v->spl_nright = 0;
! 			memcpy((void *) unionL, (void *) &pageunion, sizeof(BOX));
! 			memcpy((void *) unionR, (void *) &pageunion, sizeof(BOX));
! 
! 			for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
! 			{
! 				if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
! 				{
! 					v->spl_left[v->spl_nleft] = i;
! 					v->spl_nleft++;
! 				}
! 				else
! 				{
! 					v->spl_right[v->spl_nright] = i;
! 					v->spl_nright++;
! 				}
! 			}
! 
! 			if (v->spl_ldatum_exists)
! 				adjustBox(unionL, DatumGetBoxP(v->spl_ldatum));
! 			v->spl_ldatum = BoxPGetDatum(unionL);
! 
! 			if (v->spl_rdatum_exists)
! 				adjustBox(unionR, DatumGetBoxP(v->spl_rdatum));
! 			v->spl_rdatum = BoxPGetDatum(unionR);
! 
! 			v->spl_ldatum_exists = v->spl_rdatum_exists = false;
! 
! 			PG_RETURN_POINTER(v);
! 		}
  	}
  
  	listB = (OffsetNumber *) palloc(nbytes);
  	listT = (OffsetNumber *) palloc(nbytes);
  	unionB = (BOX *) palloc(sizeof(BOX));
  	unionT = (BOX *) palloc(sizeof(BOX));
  
--- 387,408 ----
  		adjustBox(&pageunion, cur);
  	}
  
  	if (allisequal)
  	{
! 		/*
! 		 * All entries are the same
! 		 */
! 		fallbackSplit(entryvec, v);
! 		PG_RETURN_POINTER(v);
  	}
  
+ 	nbytes = (maxoff + 2) * sizeof(OffsetNumber);
+ 	listL = (OffsetNumber *) palloc(nbytes);
+ 	listR = (OffsetNumber *) palloc(nbytes);
  	listB = (OffsetNumber *) palloc(nbytes);
  	listT = (OffsetNumber *) palloc(nbytes);
+ 	unionL = (BOX *) palloc(sizeof(BOX));
+ 	unionR = (BOX *) palloc(sizeof(BOX));
  	unionB = (BOX *) palloc(sizeof(BOX));
  	unionT = (BOX *) palloc(sizeof(BOX));
  
***************
*** 452,457 ****
--- 485,496 ----
  			else
  				ADDLIST(listT, unionT, posT, i);
  		}
+ 
+ 		if (IS_BADRATIO(posR, posL) && IS_BADRATIO(posT, posB))
+ 		{
+ 			fallbackSplit(entryvec, v);
+ 			PG_RETURN_POINTER(v);
+ 		}
  	}
  
  	/* which split more optimal? */
