/* * Equality method * * This is used for boxes, points, circles, and polygons, all of which store * boxes as GiST index entries. * * Returns true only when boxes are exactly the same. We can't use fuzzy * comparisons here without breaking index consistency; therefore, this isn't * equivalent to box_same(). */ Datum gist_box_same(PG_FUNCTION_ARGS) { BOX *b1 = PG_GETARG_BOX_P(0); BOX *b2 = PG_GETARG_BOX_P(1); bool *result = (bool *) PG_GETARG_POINTER(2); if (b1 && b2) *result = (b1->low.x == b2->low.x && b1->low.y == b2->low.y && b1->high.x == b2->high.x && b1->high.y == b2->high.y); else *result = (b1 == NULL && b2 == NULL); PG_RETURN_POINTER(result); }
/* * Equality method * * This is used for both boxes and points. */ Datum gist_box_same(PG_FUNCTION_ARGS) { BOX *b1 = PG_GETARG_BOX_P(0); BOX *b2 = PG_GETARG_BOX_P(1); bool *result = (bool *) PG_GETARG_POINTER(2); if (b1 && b2) *result = DatumGetBool(DirectFunctionCall2(box_same, PointerGetDatum(b1), PointerGetDatum(b2))); else *result = (b1 == NULL && b2 == NULL) ? TRUE : FALSE; PG_RETURN_POINTER(result); }
/* * The GiST Consistent method for boxes * * Should return false if for all data items x below entry, * the predicate x op query must be FALSE, where op is the oper * corresponding to strategy in the pg_amop table. */ Datum gist_box_consistent(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); BOX *query = PG_GETARG_BOX_P(1); StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); /* Oid subtype = PG_GETARG_OID(3); */ bool *recheck = (bool *) PG_GETARG_POINTER(4); /* All cases served by this function are exact */ *recheck = false; 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 */ if (GIST_LEAF(entry)) PG_RETURN_BOOL(gist_box_leaf_consistent(DatumGetBoxP(entry->key), query, strategy)); else PG_RETURN_BOOL(rtree_internal_consistent(DatumGetBoxP(entry->key), query, strategy)); }
static Datum rt_box_union(PG_FUNCTION_ARGS) { BOX *a = PG_GETARG_BOX_P(0); BOX *b = PG_GETARG_BOX_P(1); BOX *n; n = (BOX *) palloc(sizeof(BOX)); n->high.x = Max(a->high.x, b->high.x); n->high.y = Max(a->high.y, b->high.y); n->low.x = Min(a->low.x, b->low.x); n->low.y = Min(a->low.y, b->low.y); PG_RETURN_BOX_P(n); }
Datum boxarea(PG_FUNCTION_ARGS) { BOX *box = PG_GETARG_BOX_P(0); double width, height; width = Abs(box->high.x - box->low.x); height = Abs(box->high.y - box->low.y); PG_RETURN_FLOAT8(width * height); }
static Datum rt_box_inter(PG_FUNCTION_ARGS) { BOX *a = PG_GETARG_BOX_P(0); BOX *b = PG_GETARG_BOX_P(1); BOX *n; n = (BOX *) palloc(sizeof(BOX)); n->high.x = Min(a->high.x, b->high.x); n->high.y = Min(a->high.y, b->high.y); n->low.x = Max(a->low.x, b->low.x); n->low.y = Max(a->low.y, b->low.y); if (n->high.x < n->low.x || n->high.y < n->low.y) { pfree(n); /* Indicate "no intersection" by returning NULL pointer */ n = NULL; } PG_RETURN_BOX_P(n); }
/* * The GiST MinDist method for boxes * */ Datum gist_box_mindistance(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); BOX *query = PG_GETARG_BOX_P(1); double d; if (DatumGetBoxP(entry->key) == NULL || query == NULL) { d = get_float8_infinity(); PG_RETURN_FLOAT8(d); } d = box_mindist_internal(DatumGetBoxP(entry->key), query); PG_RETURN_FLOAT8(d); }
Datum rt_box_size(PG_FUNCTION_ARGS) { BOX *a = PG_GETARG_BOX_P(0); /* NB: size is an output argument */ float *size = (float *) PG_GETARG_POINTER(1); if (a == NULL || a->high.x <= a->low.x || a->high.y <= a->low.y) *size = 0.0; else *size = (float) ((a->high.x - a->low.x) * (a->high.y - a->low.y)); PG_RETURN_VOID(); }
Datum earth_box_to_point(PG_FUNCTION_ARGS) { //Tsquare *pc = PG_GETARG_TSQUARE(0); BOX *box = PG_GETARG_BOX_P(0); Point *result; GL_CHECK_BOX_S0(box); result = palloc(sizeof(Point)); result->x = box->low.x; result->y = box->low.y; if(earth_check_point(result) != 0) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("attempt to get a point form a cube_s0 out of range"))); PG_RETURN_POINTER(result); }
/* * The GiST Consistent method for boxes * * Should return false if for all data items x below entry, * the predicate x op query must be FALSE, where op is the oper * corresponding to strategy in the pg_amop table. */ Datum gist_box_consistent(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); BOX *query = PG_GETARG_BOX_P(1); StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); 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 */ if (GIST_LEAF(entry)) PG_RETURN_BOOL(gist_box_leaf_consistent(DatumGetBoxP(entry->key), query, strategy)); else PG_RETURN_BOOL(rtree_internal_consistent(DatumGetBoxP(entry->key), query, strategy)); }
Datum gist_point_consistent(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); bool *recheck = (bool *) PG_GETARG_POINTER(4); bool result; StrategyNumber strategyGroup = strategy / GeoStrategyNumberOffset; switch (strategyGroup) { case PointStrategyNumberGroup: result = gist_point_consistent_internal(strategy % GeoStrategyNumberOffset, GIST_LEAF(entry), DatumGetBoxP(entry->key), PG_GETARG_POINT_P(1)); *recheck = false; break; case BoxStrategyNumberGroup: { /* * The only operator___ in this group is point <@ box (on_pb), so * we needn't examine strategy again. * * For historical reasons, on_pb uses exact rather than fuzzy * comparisons. We could use box_overlap when at an internal * page, but that would lead to possibly visiting child pages * uselessly, because box_overlap uses fuzzy comparisons. * Instead we write a non-fuzzy overlap test. The same code * will also serve for leaf-page tests, since leaf keys have * high == low. */ BOX *query, *key; query = PG_GETARG_BOX_P(1); key = DatumGetBoxP(entry->key); 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); *recheck = false; } break; case PolygonStrategyNumberGroup: { POLYGON *query = PG_GETARG_POLYGON_P(1); result = DatumGetBool(DirectFunctionCall5( gist_poly_consistent, PointerGetDatum(entry), PolygonPGetDatum(query), Int16GetDatum(RTOverlapStrategyNumber), 0, PointerGetDatum(recheck))); if (GIST_LEAF(entry) && result) { /* * We are on leaf page and quick check shows overlapping * of polygon's bounding box and point */ BOX *box = DatumGetBoxP(entry->key); Assert(box->high.x == box->low.x && box->high.y == box->low.y); result = DatumGetBool(DirectFunctionCall2( poly_contain_pt, PolygonPGetDatum(query), PointPGetDatum(&box->high))); *recheck = false; } } break; case CircleStrategyNumberGroup: { CIRCLE *query = PG_GETARG_CIRCLE_P(1); result = DatumGetBool(DirectFunctionCall5( gist_circle_consistent, PointerGetDatum(entry), CirclePGetDatum(query), Int16GetDatum(RTOverlapStrategyNumber), 0, PointerGetDatum(recheck))); if (GIST_LEAF(entry) && result) { /* * We are on leaf page and quick check shows overlapping * of polygon's bounding box and point */ BOX *box = DatumGetBoxP(entry->key); Assert(box->high.x == box->low.x && box->high.y == box->low.y); result = DatumGetBool(DirectFunctionCall2( circle_contain_pt, CirclePGetDatum(query), PointPGetDatum(&box->high))); *recheck = false; } } break; default: elog(ERROR, "unrecognized strategy number: %d", strategy); result = false; /* keep compiler quiet */ break; } PG_RETURN_BOOL(result); }