1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-11 20:28:21 +03:00

Add point_ops opclass for GiST.

This commit is contained in:
Teodor Sigaev
2010-01-14 16:31:09 +00:00
parent e99767bc28
commit 4cbe473938
16 changed files with 511 additions and 20 deletions

View File

@ -10,7 +10,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/gist/gistproc.c,v 1.19 2010/01/02 16:57:34 momjian Exp $
* $PostgreSQL: pgsql/src/backend/access/gist/gistproc.c,v 1.20 2010/01/14 16:31:09 teodor Exp $
*
*-------------------------------------------------------------------------
*/
@ -165,7 +165,8 @@ gist_box_compress(PG_FUNCTION_ARGS)
}
/*
* GiST DeCompress method for boxes (also used for polygons and circles)
* GiST DeCompress method for boxes (also used for points, polygons
* and circles)
*
* do not do anything --- we just use the stored box as is.
*/
@ -176,7 +177,7 @@ gist_box_decompress(PG_FUNCTION_ARGS)
}
/*
* The GiST Penalty method for boxes
* The GiST Penalty method for boxes (also used for points)
*
* As in the R-tree paper, we use change in area as our penalty metric
*/
@ -341,6 +342,8 @@ fallbackSplit(GistEntryVector *entryvec, GIST_SPLITVEC *v)
*
* New linear algorithm, see 'New Linear Node Splitting Algorithm for R-tree',
* C.H.Ang and T.C.Tan
*
* This is used for both boxes and points.
*/
Datum
gist_box_picksplit(PG_FUNCTION_ARGS)
@ -533,6 +536,8 @@ gist_box_picksplit(PG_FUNCTION_ARGS)
/*
* Equality method
*
* This is used for both boxes and points.
*/
Datum
gist_box_same(PG_FUNCTION_ARGS)
@ -872,3 +877,166 @@ gist_circle_consistent(PG_FUNCTION_ARGS)
PG_RETURN_BOOL(result);
}
/**************************************************
* Point ops
**************************************************/
Datum
gist_point_compress(PG_FUNCTION_ARGS)
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
if (entry->leafkey) /* Point, actually */
{
BOX *box = palloc(sizeof(BOX));
Point *point = DatumGetPointP(entry->key);
GISTENTRY *retval = palloc(sizeof(GISTENTRY));
box->high = box->low = *point;
gistentryinit(*retval, BoxPGetDatum(box),
entry->rel, entry->page, entry->offset, FALSE);
PG_RETURN_POINTER(retval);
}
PG_RETURN_POINTER(entry);
}
static bool
gist_point_consistent_internal(StrategyNumber strategy,
bool isLeaf, BOX *key, Point *query)
{
bool result = false;
switch (strategy)
{
case RTLeftStrategyNumber:
result = FPlt(key->low.x, query->x);
break;
case RTRightStrategyNumber:
result = FPgt(key->high.x, query->x);
break;
case RTAboveStrategyNumber:
result = FPgt(key->high.y, query->y);
break;
case RTBelowStrategyNumber:
result = FPlt(key->low.y, query->y);
break;
case RTSameStrategyNumber:
if (isLeaf)
{
result = FPeq(key->low.x, query->x)
&& FPeq(key->low.y, query->y);
}
else
{
result = (query->x <= key->high.x && query->x >= key->low.x &&
query->y <= key->high.y && query->y >= key->low.y);
}
break;
default:
elog(ERROR, "unknown strategy number: %d", strategy);
}
return result;
}
#define GeoStrategyNumberOffset 20
#define PointStrategyNumberGroup 0
#define BoxStrategyNumberGroup 1
#define PolygonStrategyNumberGroup 2
#define CircleStrategyNumberGroup 3
Datum
gist_point_consistent(PG_FUNCTION_ARGS)
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
bool result;
bool *recheck = (bool *) PG_GETARG_POINTER(4);
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:
result = DatumGetBool(DirectFunctionCall5(
gist_box_consistent,
PointerGetDatum(entry),
PG_GETARG_DATUM(1),
Int16GetDatum(RTOverlapStrategyNumber),
0, PointerGetDatum(recheck)));
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:
result = false; /* silence compiler warning */
elog(ERROR, "unknown strategy number: %d", strategy);
}
PG_RETURN_BOOL(result);
}