1010 * Portions Copyright (c) 1994, Regents of the University of California
1111 *
1212 * IDENTIFICATION
13- * $PostgreSQL: pgsql/src/backend/access/gist/gistproc.c,v 1.19 2010/01/02 16:57:34 momjian Exp $
13+ * $PostgreSQL: pgsql/src/backend/access/gist/gistproc.c,v 1.20 2010/01/14 16:31:09 teodor Exp $
1414 *
1515 *-------------------------------------------------------------------------
1616 */
@@ -165,7 +165,8 @@ gist_box_compress(PG_FUNCTION_ARGS)
165165}
166166
167167/*
168- * GiST DeCompress method for boxes (also used for polygons and circles)
168+ * GiST DeCompress method for boxes (also used for points, polygons
169+ * and circles)
169170 *
170171 * do not do anything --- we just use the stored box as is.
171172 */
@@ -176,7 +177,7 @@ gist_box_decompress(PG_FUNCTION_ARGS)
176177}
177178
178179/*
179- * The GiST Penalty method for boxes
180+ * The GiST Penalty method for boxes (also used for points)
180181 *
181182 * As in the R-tree paper, we use change in area as our penalty metric
182183 */
@@ -341,6 +342,8 @@ fallbackSplit(GistEntryVector *entryvec, GIST_SPLITVEC *v)
341342 *
342343 * New linear algorithm, see 'New Linear Node Splitting Algorithm for R-tree',
343344 * C.H.Ang and T.C.Tan
345+ *
346+ * This is used for both boxes and points.
344347 */
345348Datum
346349gist_box_picksplit (PG_FUNCTION_ARGS )
@@ -533,6 +536,8 @@ gist_box_picksplit(PG_FUNCTION_ARGS)
533536
534537/*
535538 * Equality method
539+ *
540+ * This is used for both boxes and points.
536541 */
537542Datum
538543gist_box_same (PG_FUNCTION_ARGS )
@@ -872,3 +877,166 @@ gist_circle_consistent(PG_FUNCTION_ARGS)
872877
873878 PG_RETURN_BOOL (result );
874879}
880+
881+ /**************************************************
882+ * Point ops
883+ **************************************************/
884+
885+ Datum
886+ gist_point_compress (PG_FUNCTION_ARGS )
887+ {
888+ GISTENTRY * entry = (GISTENTRY * ) PG_GETARG_POINTER (0 );
889+
890+ if (entry -> leafkey ) /* Point, actually */
891+ {
892+ BOX * box = palloc (sizeof (BOX ));
893+ Point * point = DatumGetPointP (entry -> key );
894+ GISTENTRY * retval = palloc (sizeof (GISTENTRY ));
895+
896+ box -> high = box -> low = * point ;
897+
898+ gistentryinit (* retval , BoxPGetDatum (box ),
899+ entry -> rel , entry -> page , entry -> offset , FALSE);
900+
901+ PG_RETURN_POINTER (retval );
902+ }
903+
904+ PG_RETURN_POINTER (entry );
905+ }
906+
907+ static bool
908+ gist_point_consistent_internal (StrategyNumber strategy ,
909+ bool isLeaf , BOX * key , Point * query )
910+ {
911+ bool result = false;
912+
913+ switch (strategy )
914+ {
915+ case RTLeftStrategyNumber :
916+ result = FPlt (key -> low .x , query -> x );
917+ break ;
918+ case RTRightStrategyNumber :
919+ result = FPgt (key -> high .x , query -> x );
920+ break ;
921+ case RTAboveStrategyNumber :
922+ result = FPgt (key -> high .y , query -> y );
923+ break ;
924+ case RTBelowStrategyNumber :
925+ result = FPlt (key -> low .y , query -> y );
926+ break ;
927+ case RTSameStrategyNumber :
928+ if (isLeaf )
929+ {
930+ result = FPeq (key -> low .x , query -> x )
931+ && FPeq (key -> low .y , query -> y );
932+ }
933+ else
934+ {
935+ result = (query -> x <= key -> high .x && query -> x >= key -> low .x &&
936+ query -> y <= key -> high .y && query -> y >= key -> low .y );
937+ }
938+ break ;
939+ default :
940+ elog (ERROR , "unknown strategy number: %d" , strategy );
941+ }
942+
943+ return result ;
944+ }
945+
946+ #define GeoStrategyNumberOffset 20
947+ #define PointStrategyNumberGroup 0
948+ #define BoxStrategyNumberGroup 1
949+ #define PolygonStrategyNumberGroup 2
950+ #define CircleStrategyNumberGroup 3
951+
952+ Datum
953+ gist_point_consistent (PG_FUNCTION_ARGS )
954+ {
955+ GISTENTRY * entry = (GISTENTRY * ) PG_GETARG_POINTER (0 );
956+ StrategyNumber strategy = (StrategyNumber ) PG_GETARG_UINT16 (2 );
957+ bool result ;
958+ bool * recheck = (bool * ) PG_GETARG_POINTER (4 );
959+ StrategyNumber strategyGroup = strategy / GeoStrategyNumberOffset ;
960+
961+ switch (strategyGroup )
962+ {
963+ case PointStrategyNumberGroup :
964+ result = gist_point_consistent_internal (strategy % GeoStrategyNumberOffset ,
965+ GIST_LEAF (entry ),
966+ DatumGetBoxP (entry -> key ),
967+ PG_GETARG_POINT_P (1 ));
968+ * recheck = false;
969+ break ;
970+ case BoxStrategyNumberGroup :
971+ result = DatumGetBool (DirectFunctionCall5 (
972+ gist_box_consistent ,
973+ PointerGetDatum (entry ),
974+ PG_GETARG_DATUM (1 ),
975+ Int16GetDatum (RTOverlapStrategyNumber ),
976+ 0 , PointerGetDatum (recheck )));
977+ break ;
978+ case PolygonStrategyNumberGroup :
979+ {
980+ POLYGON * query = PG_GETARG_POLYGON_P (1 );
981+
982+ result = DatumGetBool (DirectFunctionCall5 (
983+ gist_poly_consistent ,
984+ PointerGetDatum (entry ),
985+ PolygonPGetDatum (query ),
986+ Int16GetDatum (RTOverlapStrategyNumber ),
987+ 0 , PointerGetDatum (recheck )));
988+
989+ if (GIST_LEAF (entry ) && result )
990+ {
991+ /*
992+ * We are on leaf page and quick check shows overlapping
993+ * of polygon's bounding box and point
994+ */
995+ BOX * box = DatumGetBoxP (entry -> key );
996+
997+ Assert (box -> high .x == box -> low .x
998+ && box -> high .y == box -> low .y );
999+ result = DatumGetBool (DirectFunctionCall2 (
1000+ poly_contain_pt ,
1001+ PolygonPGetDatum (query ),
1002+ PointPGetDatum (& box -> high )));
1003+ * recheck = false;
1004+ }
1005+ }
1006+ break ;
1007+ case CircleStrategyNumberGroup :
1008+ {
1009+ CIRCLE * query = PG_GETARG_CIRCLE_P (1 );
1010+
1011+ result = DatumGetBool (DirectFunctionCall5 (
1012+ gist_circle_consistent ,
1013+ PointerGetDatum (entry ),
1014+ CirclePGetDatum (query ),
1015+ Int16GetDatum (RTOverlapStrategyNumber ),
1016+ 0 , PointerGetDatum (recheck )));
1017+
1018+ if (GIST_LEAF (entry ) && result )
1019+ {
1020+ /*
1021+ * We are on leaf page and quick check shows overlapping
1022+ * of polygon's bounding box and point
1023+ */
1024+ BOX * box = DatumGetBoxP (entry -> key );
1025+
1026+ Assert (box -> high .x == box -> low .x
1027+ && box -> high .y == box -> low .y );
1028+ result = DatumGetBool (DirectFunctionCall2 (
1029+ circle_contain_pt ,
1030+ CirclePGetDatum (query ),
1031+ PointPGetDatum (& box -> high )));
1032+ * recheck = false;
1033+ }
1034+ }
1035+ break ;
1036+ default :
1037+ result = false; /* silence compiler warning */
1038+ elog (ERROR , "unknown strategy number: %d" , strategy );
1039+ }
1040+
1041+ PG_RETURN_BOOL (result );
1042+ }
0 commit comments