summaryrefslogtreecommitdiff
path: root/src/backend/access/gist/gistproc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access/gist/gistproc.c')
-rw-r--r--src/backend/access/gist/gistproc.c174
1 files changed, 171 insertions, 3 deletions
diff --git a/src/backend/access/gist/gistproc.c b/src/backend/access/gist/gistproc.c
index cf3442763e..18ee0259a5 100644
--- a/src/backend/access/gist/gistproc.c
+++ b/src/backend/access/gist/gistproc.c
@@ -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);
+}