*** 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: {