10
10
* Portions Copyright (c) 1994, Regents of the University of California
11
11
*
12
12
* 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 $
14
14
*
15
15
*-------------------------------------------------------------------------
16
16
*/
@@ -165,7 +165,8 @@ gist_box_compress(PG_FUNCTION_ARGS)
165
165
}
166
166
167
167
/*
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)
169
170
*
170
171
* do not do anything --- we just use the stored box as is.
171
172
*/
@@ -176,7 +177,7 @@ gist_box_decompress(PG_FUNCTION_ARGS)
176
177
}
177
178
178
179
/*
179
- * The GiST Penalty method for boxes
180
+ * The GiST Penalty method for boxes (also used for points)
180
181
*
181
182
* As in the R-tree paper, we use change in area as our penalty metric
182
183
*/
@@ -341,6 +342,8 @@ fallbackSplit(GistEntryVector *entryvec, GIST_SPLITVEC *v)
341
342
*
342
343
* New linear algorithm, see 'New Linear Node Splitting Algorithm for R-tree',
343
344
* C.H.Ang and T.C.Tan
345
+ *
346
+ * This is used for both boxes and points.
344
347
*/
345
348
Datum
346
349
gist_box_picksplit (PG_FUNCTION_ARGS )
@@ -533,6 +536,8 @@ gist_box_picksplit(PG_FUNCTION_ARGS)
533
536
534
537
/*
535
538
* Equality method
539
+ *
540
+ * This is used for both boxes and points.
536
541
*/
537
542
Datum
538
543
gist_box_same (PG_FUNCTION_ARGS )
@@ -872,3 +877,166 @@ gist_circle_consistent(PG_FUNCTION_ARGS)
872
877
873
878
PG_RETURN_BOOL (result );
874
879
}
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