I believe that attached version of patch can be backpatched. It fixes this
problem without altering of index building procedure. It just makes checks
in internal pages softener enough to compensate effect of gist_box_same
implementation.

------
With best regards,
Alexander Korotkov.
*** a/src/backend/access/gist/gistproc.c
--- b/src/backend/access/gist/gistproc.c
***************
*** 70,76 **** gist_box_consistent(PG_FUNCTION_ARGS)
  
  	if (DatumGetBoxP(entry->key) == NULL || query == NULL)
  		PG_RETURN_BOOL(FALSE);
! 
  	/*
  	 * if entry is not leaf, use rtree_internal_consistent, else use
  	 * gist_box_leaf_consistent
--- 70,76 ----
  
  	if (DatumGetBoxP(entry->key) == NULL || query == NULL)
  		PG_RETURN_BOOL(FALSE);
! 	
  	/*
  	 * if entry is not leaf, use rtree_internal_consistent, else use
  	 * gist_box_leaf_consistent
***************
*** 80,88 **** gist_box_consistent(PG_FUNCTION_ARGS)
  												query,
  												strategy));
  	else
! 		PG_RETURN_BOOL(rtree_internal_consistent(DatumGetBoxP(entry->key),
  												 query,
  												 strategy));
  }
  
  static void
--- 80,102 ----
  												query,
  												strategy));
  	else
! 	{
! 		/*
! 		 * Box in internal page can be narrower than box in leaf page not
! 		 * more than EPSILON in each boundary. Do corresponding correction.
! 		 */
! 		BOX			key, *entrykey;
! 		
! 		entrykey = DatumGetBoxP(entry->key);
! 		key.low.x = entrykey->low.x - EPSILON;
! 		key.low.y = entrykey->low.y - EPSILON;
! 		key.high.x = entrykey->high.x + EPSILON;
! 		key.high.y = entrykey->high.y + EPSILON;
! 		
! 		PG_RETURN_BOOL(rtree_internal_consistent(&key,
  												 query,
  												 strategy));
+ 	}
  }
  
  static void
***************
*** 847,852 **** gist_box_same(PG_FUNCTION_ARGS)
--- 861,871 ----
  	BOX		   *b2 = PG_GETARG_BOX_P(1);
  	bool	   *result = (bool *) PG_GETARG_POINTER(2);
  
+ 	/*
+ 	 * box_same function allow difference between boxes limited by EPSILON.
+ 	 * Thus box in internal page can be narrower than box in leaf page not
+ 	 * more than EPSILON in each boundary.
+ 	 */
  	if (b1 && b2)
  		*result = DatumGetBool(DirectFunctionCall2(box_same,
  												   PointerGetDatum(b1),
***************
*** 1072,1077 **** gist_poly_consistent(PG_FUNCTION_ARGS)
--- 1091,1097 ----
  	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
  	POLYGON    *query = PG_GETARG_POLYGON_P(1);
  	StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
+ 	BOX			key, *entrykey;
  
  	/* Oid		subtype = PG_GETARG_OID(3); */
  	bool	   *recheck = (bool *) PG_GETARG_POINTER(4);
***************
*** 1083,1094 **** gist_poly_consistent(PG_FUNCTION_ARGS)
  	if (DatumGetBoxP(entry->key) == NULL || query == NULL)
  		PG_RETURN_BOOL(FALSE);
  
  	/*
  	 * Since the operators require recheck anyway, we can just use
  	 * rtree_internal_consistent even at leaf nodes.  (This works in part
  	 * because the index entries are bounding boxes not polygons.)
  	 */
! 	result = rtree_internal_consistent(DatumGetBoxP(entry->key),
  									   &(query->boundbox), strategy);
  
  	/* Avoid memory leak if supplied poly is toasted */
--- 1103,1128 ----
  	if (DatumGetBoxP(entry->key) == NULL || query == NULL)
  		PG_RETURN_BOOL(FALSE);
  
+ 	entrykey = DatumGetBoxP(entry->key);
+ 	if (!GIST_LEAF(entry))
+ 	{
+ 		/*
+ 		 * Box in internal page can be narrower than box in leaf page not
+ 		 * more than EPSILON in each boundary. Do corresponding correction.
+ 		 */
+ 		key.low.x = entrykey->low.x - EPSILON;
+ 		key.low.y = entrykey->low.y - EPSILON;
+ 		key.high.x = entrykey->high.x + EPSILON;
+ 		key.high.y = entrykey->high.y + EPSILON;
+ 		entrykey = &key;
+ 	}
+ 	
  	/*
  	 * Since the operators require recheck anyway, we can just use
  	 * rtree_internal_consistent even at leaf nodes.  (This works in part
  	 * because the index entries are bounding boxes not polygons.)
  	 */
! 	result = rtree_internal_consistent(entrykey,
  									   &(query->boundbox), strategy);
  
  	/* Avoid memory leak if supplied poly is toasted */
***************
*** 1152,1158 **** gist_circle_consistent(PG_FUNCTION_ARGS)
  
  	/* Oid		subtype = PG_GETARG_OID(3); */
  	bool	   *recheck = (bool *) PG_GETARG_POINTER(4);
! 	BOX			bbox;
  	bool		result;
  
  	/* All cases served by this function are inexact */
--- 1186,1192 ----
  
  	/* Oid		subtype = PG_GETARG_OID(3); */
  	bool	   *recheck = (bool *) PG_GETARG_POINTER(4);
! 	BOX			bbox, *entrykey, key;
  	bool		result;
  
  	/* All cases served by this function are inexact */
***************
*** 1170,1177 **** gist_circle_consistent(PG_FUNCTION_ARGS)
  	bbox.low.x = query->center.x - query->radius;
  	bbox.high.y = query->center.y + query->radius;
  	bbox.low.y = query->center.y - query->radius;
  
! 	result = rtree_internal_consistent(DatumGetBoxP(entry->key),
  									   &bbox, strategy);
  
  	PG_RETURN_BOOL(result);
--- 1204,1225 ----
  	bbox.low.x = query->center.x - query->radius;
  	bbox.high.y = query->center.y + query->radius;
  	bbox.low.y = query->center.y - query->radius;
+ 	
+ 	entrykey = DatumGetBoxP(entry->key);
+ 	if (!GIST_LEAF(entry))
+ 	{
+ 		/*
+ 		 * Box in internal page can be narrower than box in leaf page not
+ 		 * more than EPSILON in each boundary. Do corresponding correction.
+ 		 */
+ 		key.low.x = entrykey->low.x - EPSILON;
+ 		key.low.y = entrykey->low.y - EPSILON;
+ 		key.high.x = entrykey->high.x + EPSILON;
+ 		key.high.y = entrykey->high.y + EPSILON;
+ 		entrykey = &key;
+ 	}
  
! 	result = rtree_internal_consistent(entrykey,
  									   &bbox, strategy);
  
  	PG_RETURN_BOOL(result);
***************
*** 1337,1348 **** gist_point_consistent(PG_FUNCTION_ARGS)
  			*recheck = false;
  			break;
  		case BoxStrategyNumberGroup:
! 			result = DatumGetBool(DirectFunctionCall5(
! 													  gist_box_consistent,
! 													  PointerGetDatum(entry),
! 													  PG_GETARG_DATUM(1),
! 									  Int16GetDatum(RTOverlapStrategyNumber),
! 											   0, PointerGetDatum(recheck)));
  			break;
  		case PolygonStrategyNumberGroup:
  			{
--- 1385,1419 ----
  			*recheck = false;
  			break;
  		case BoxStrategyNumberGroup:
! 			{
! 				/*
! 				 * This strategy should behave like on_ob which uses simple
! 				 * comparison rather than FP* functions. Thus we use simple
! 				 * comparison for leaf entries. Also we use box_overlap which
! 				 * allows difference not more than EPSILON compensating
! 				 * possible narrower boxes in internal pages.
! 				 */
! 				
! 				BOX	   *query = PG_GETARG_BOX_P(1);
! 				
! 				if (GIST_LEAF(entry))
! 				{
! 					BOX *key;
! 					key = DatumGetBoxP(entry->key);
! 					*recheck = false;
! 					result = key->high.x >= query->low.x && 
! 							 key->low.x <= query->high.x &&
! 							 key->high.y >= query->low.y && 
! 							 key->low.y <= query->high.y;
! 				}
! 				else
! 				{
! 					result = DatumGetBool(DirectFunctionCall2(
! 																 box_overlap,
! 																  entry->key,
! 													PointerGetDatum(query)));
! 				}
! 			}
  			break;
  		case PolygonStrategyNumberGroup:
  			{
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to