Adjust contrib/seg &< and &> operators so that r-tree indexing logic

works properly for 1-D comparisons.  Fix some other errors such as
bogus commutator specifications.
This commit is contained in:
Tom Lane 2005-06-27 00:48:07 +00:00
parent 06ae88a82e
commit 54c80a3434
5 changed files with 60 additions and 54 deletions

View file

@ -214,7 +214,7 @@ have just 2 significant digits.
USAGE USAGE
===== =====
The access method for SEG is a GiST (gist_seg_ops), which is a The access method for SEG is a GiST index (gist_seg_ops), which is a
generalization of R-tree. GiSTs allow the postgres implementation of generalization of R-tree. GiSTs allow the postgres implementation of
R-tree, originally encoded to support 2-D geometric types such as R-tree, originally encoded to support 2-D geometric types such as
boxes and polygons, to be used with any data type whose data domain boxes and polygons, to be used with any data type whose data domain
@ -236,23 +236,27 @@ The operators supported by the GiST access method include:
[a, b] >> [c, d] Is right of [a, b] >> [c, d] Is right of
[a, b] is occurs entirely to the right of [c, d]. [a, b] is occurs entirely to the right of [c, d].
[a, b] >> [c, d] is true if b > c and false otherwise [a, b] >> [c, d] is true if a > d and false otherwise
[a, b] &< [c, d] Over left [a, b] &< [c, d] Overlaps or is left of
The segment [a, b] overlaps the segment [c, d] in such a way This might be better read as "does not extend to right of".
that a <= c <= b and b <= d It is true when b <= d.
[a, b] &> [c, d] Over right [a, b] &> [c, d] Overlaps or is right of
The segment [a, b] overlaps the segment [c, d] in such a way This might be better read as "does not extend to left of".
that a > c and b <= c <= d It is true when a >= c.
[a, b] = [c, d] Same as [a, b] = [c, d] Same as
The segments [a, b] and [c, d] are identical, that is, a == b The segments [a, b] and [c, d] are identical, that is, a == b
and c == d and c == d
[a, b] && [c, d] Overlaps
The segments [a, b] and [c, d] overlap.
[a, b] @ [c, d] Contains [a, b] @ [c, d] Contains
The segment [a, b] contains the segment [c, d], that is, The segment [a, b] contains the segment [c, d], that is,

View file

@ -557,7 +557,7 @@ SELECT '1'::seg &< '1'::seg AS bool;
SELECT '1'::seg &< '2'::seg AS bool; SELECT '1'::seg &< '2'::seg AS bool;
bool bool
------ ------
f t
(1 row) (1 row)
SELECT '0 .. 1'::seg &< '0'::seg AS bool; SELECT '0 .. 1'::seg &< '0'::seg AS bool;
@ -575,7 +575,7 @@ SELECT '0 .. 1'::seg &< '1'::seg AS bool;
SELECT '0 .. 1'::seg &< '2'::seg AS bool; SELECT '0 .. 1'::seg &< '2'::seg AS bool;
bool bool
------ ------
f t
(1 row) (1 row)
SELECT '0 .. 1'::seg &< '0 .. 0.5'::seg AS bool; SELECT '0 .. 1'::seg &< '0 .. 0.5'::seg AS bool;
@ -605,7 +605,7 @@ SELECT '0 .. 1'::seg &< '1 .. 2'::seg AS bool;
SELECT '0 .. 1'::seg &< '2 .. 3'::seg AS bool; SELECT '0 .. 1'::seg &< '2 .. 3'::seg AS bool;
bool bool
------ ------
f t
(1 row) (1 row)
-- overlap on the right -- overlap on the right
@ -625,7 +625,7 @@ SELECT '1'::seg &> '1'::seg AS bool;
SELECT '2'::seg &> '1'::seg AS bool; SELECT '2'::seg &> '1'::seg AS bool;
bool bool
------ ------
f t
(1 row) (1 row)
SELECT '0'::seg &> '0 .. 1'::seg AS bool; SELECT '0'::seg &> '0 .. 1'::seg AS bool;
@ -643,7 +643,7 @@ SELECT '1'::seg &> '0 .. 1'::seg AS bool;
SELECT '2'::seg &> '0 .. 1'::seg AS bool; SELECT '2'::seg &> '0 .. 1'::seg AS bool;
bool bool
------ ------
f t
(1 row) (1 row)
SELECT '0 .. 0.5'::seg &> '0 .. 1'::seg AS bool; SELECT '0 .. 0.5'::seg &> '0 .. 1'::seg AS bool;
@ -673,7 +673,7 @@ SELECT '1 .. 2'::seg &> '0 .. 1'::seg AS bool;
SELECT '2 .. 3'::seg &> '0 .. 1'::seg AS bool; SELECT '2 .. 3'::seg &> '0 .. 1'::seg AS bool;
bool bool
------ ------
f t
(1 row) (1 row)
-- left -- left

View file

@ -557,7 +557,7 @@ SELECT '1'::seg &< '1'::seg AS bool;
SELECT '1'::seg &< '2'::seg AS bool; SELECT '1'::seg &< '2'::seg AS bool;
bool bool
------ ------
f t
(1 row) (1 row)
SELECT '0 .. 1'::seg &< '0'::seg AS bool; SELECT '0 .. 1'::seg &< '0'::seg AS bool;
@ -575,7 +575,7 @@ SELECT '0 .. 1'::seg &< '1'::seg AS bool;
SELECT '0 .. 1'::seg &< '2'::seg AS bool; SELECT '0 .. 1'::seg &< '2'::seg AS bool;
bool bool
------ ------
f t
(1 row) (1 row)
SELECT '0 .. 1'::seg &< '0 .. 0.5'::seg AS bool; SELECT '0 .. 1'::seg &< '0 .. 0.5'::seg AS bool;
@ -605,7 +605,7 @@ SELECT '0 .. 1'::seg &< '1 .. 2'::seg AS bool;
SELECT '0 .. 1'::seg &< '2 .. 3'::seg AS bool; SELECT '0 .. 1'::seg &< '2 .. 3'::seg AS bool;
bool bool
------ ------
f t
(1 row) (1 row)
-- overlap on the right -- overlap on the right
@ -625,7 +625,7 @@ SELECT '1'::seg &> '1'::seg AS bool;
SELECT '2'::seg &> '1'::seg AS bool; SELECT '2'::seg &> '1'::seg AS bool;
bool bool
------ ------
f t
(1 row) (1 row)
SELECT '0'::seg &> '0 .. 1'::seg AS bool; SELECT '0'::seg &> '0 .. 1'::seg AS bool;
@ -643,7 +643,7 @@ SELECT '1'::seg &> '0 .. 1'::seg AS bool;
SELECT '2'::seg &> '0 .. 1'::seg AS bool; SELECT '2'::seg &> '0 .. 1'::seg AS bool;
bool bool
------ ------
f t
(1 row) (1 row)
SELECT '0 .. 0.5'::seg &> '0 .. 1'::seg AS bool; SELECT '0 .. 0.5'::seg &> '0 .. 1'::seg AS bool;
@ -673,7 +673,7 @@ SELECT '1 .. 2'::seg &> '0 .. 1'::seg AS bool;
SELECT '2 .. 3'::seg &> '0 .. 1'::seg AS bool; SELECT '2 .. 3'::seg &> '0 .. 1'::seg AS bool;
bool bool
------ ------
f t
(1 row) (1 row)
-- left -- left

View file

@ -204,7 +204,7 @@ gseg_consistent(GISTENTRY *entry,
StrategyNumber strategy) StrategyNumber strategy)
{ {
/* /*
* * if entry is not leaf, use gseg_internal_consistent, * else use * if entry is not leaf, use gseg_internal_consistent, else use
* gseg_leaf_consistent * gseg_leaf_consistent
*/ */
if (GIST_LEAF(entry)) if (GIST_LEAF(entry))
@ -517,15 +517,19 @@ gseg_internal_consistent(SEG * key,
switch (strategy) switch (strategy)
{ {
case RTLeftStrategyNumber: case RTLeftStrategyNumber:
retval = (bool) !seg_over_right(key, query);
break;
case RTOverLeftStrategyNumber: case RTOverLeftStrategyNumber:
retval = (bool) seg_over_left(key, query); retval = (bool) !seg_right(key, query);
break; break;
case RTOverlapStrategyNumber: case RTOverlapStrategyNumber:
retval = (bool) seg_overlap(key, query); retval = (bool) seg_overlap(key, query);
break; break;
case RTOverRightStrategyNumber: case RTOverRightStrategyNumber:
retval = (bool) !seg_left(key, query);
break;
case RTRightStrategyNumber: case RTRightStrategyNumber:
retval = (bool) seg_right(key, query); retval = (bool) !seg_over_left(key, query);
break; break;
case RTSameStrategyNumber: case RTSameStrategyNumber:
case RTContainsStrategyNumber: case RTContainsStrategyNumber:
@ -586,12 +590,12 @@ seg_overlap(SEG * a, SEG * b)
); );
} }
/* seg_overleft -- is the right edge of (a) located to the left of the right edge of (b)? /* seg_overleft -- is the right edge of (a) located at or left of the right edge of (b)?
*/ */
bool bool
seg_over_left(SEG * a, SEG * b) seg_over_left(SEG * a, SEG * b)
{ {
return (a->upper <= b->upper && !seg_left(a, b) && !seg_right(a, b)); return (a->upper <= b->upper);
} }
/* seg_left -- is (a) entirely on the left of (b)? /* seg_left -- is (a) entirely on the left of (b)?
@ -610,12 +614,12 @@ seg_right(SEG * a, SEG * b)
return (a->lower > b->upper); return (a->lower > b->upper);
} }
/* seg_overright -- is the left edge of (a) located to the right of the left edge of (b)? /* seg_overright -- is the left edge of (a) located at or right of the left edge of (b)?
*/ */
bool bool
seg_over_right(SEG * a, SEG * b) seg_over_right(SEG * a, SEG * b)
{ {
return (a->lower >= b->lower && !seg_left(a, b) && !seg_right(a, b)); return (a->lower >= b->lower);
} }

View file

@ -32,23 +32,23 @@ COMMENT ON TYPE seg IS
CREATE FUNCTION seg_over_left(seg, seg) CREATE FUNCTION seg_over_left(seg, seg)
RETURNS bool RETURNS bool
AS 'MODULE_PATHNAME' AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict); LANGUAGE 'C' STRICT IMMUTABLE;
COMMENT ON FUNCTION seg_over_left(seg, seg) IS COMMENT ON FUNCTION seg_over_left(seg, seg) IS
'is over and left of'; 'overlaps or is left of';
CREATE FUNCTION seg_over_right(seg, seg) CREATE FUNCTION seg_over_right(seg, seg)
RETURNS bool RETURNS bool
AS 'MODULE_PATHNAME' AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict); LANGUAGE 'C' STRICT IMMUTABLE;
COMMENT ON FUNCTION seg_over_right(seg, seg) IS COMMENT ON FUNCTION seg_over_right(seg, seg) IS
'is over and right of'; 'overlaps or is right of';
CREATE FUNCTION seg_left(seg, seg) CREATE FUNCTION seg_left(seg, seg)
RETURNS bool RETURNS bool
AS 'MODULE_PATHNAME' AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict); LANGUAGE 'C' STRICT IMMUTABLE;
COMMENT ON FUNCTION seg_left(seg, seg) IS COMMENT ON FUNCTION seg_left(seg, seg) IS
'is left of'; 'is left of';
@ -56,18 +56,18 @@ COMMENT ON FUNCTION seg_left(seg, seg) IS
CREATE FUNCTION seg_right(seg, seg) CREATE FUNCTION seg_right(seg, seg)
RETURNS bool RETURNS bool
AS 'MODULE_PATHNAME' AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict); LANGUAGE 'C' STRICT IMMUTABLE;
COMMENT ON FUNCTION seg_right(seg, seg) IS COMMENT ON FUNCTION seg_right(seg, seg) IS
'is right of'; 'is right of';
-- Comparison methods -- Scalar comparison methods
CREATE FUNCTION seg_lt(seg, seg) CREATE FUNCTION seg_lt(seg, seg)
RETURNS bool RETURNS bool
AS 'MODULE_PATHNAME' AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict); LANGUAGE 'C' STRICT IMMUTABLE;
COMMENT ON FUNCTION seg_lt(seg, seg) IS COMMENT ON FUNCTION seg_lt(seg, seg) IS
'less than'; 'less than';
@ -75,7 +75,7 @@ COMMENT ON FUNCTION seg_lt(seg, seg) IS
CREATE FUNCTION seg_le(seg, seg) CREATE FUNCTION seg_le(seg, seg)
RETURNS bool RETURNS bool
AS 'MODULE_PATHNAME' AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict); LANGUAGE 'C' STRICT IMMUTABLE;
COMMENT ON FUNCTION seg_le(seg, seg) IS COMMENT ON FUNCTION seg_le(seg, seg) IS
'less than or equal'; 'less than or equal';
@ -83,7 +83,7 @@ COMMENT ON FUNCTION seg_le(seg, seg) IS
CREATE FUNCTION seg_gt(seg, seg) CREATE FUNCTION seg_gt(seg, seg)
RETURNS bool RETURNS bool
AS 'MODULE_PATHNAME' AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict); LANGUAGE 'C' STRICT IMMUTABLE;
COMMENT ON FUNCTION seg_gt(seg, seg) IS COMMENT ON FUNCTION seg_gt(seg, seg) IS
'greater than'; 'greater than';
@ -91,7 +91,7 @@ COMMENT ON FUNCTION seg_gt(seg, seg) IS
CREATE FUNCTION seg_ge(seg, seg) CREATE FUNCTION seg_ge(seg, seg)
RETURNS bool RETURNS bool
AS 'MODULE_PATHNAME' AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict); LANGUAGE 'C' STRICT IMMUTABLE;
COMMENT ON FUNCTION seg_ge(seg, seg) IS COMMENT ON FUNCTION seg_ge(seg, seg) IS
'greater than or equal'; 'greater than or equal';
@ -99,7 +99,7 @@ COMMENT ON FUNCTION seg_ge(seg, seg) IS
CREATE FUNCTION seg_contains(seg, seg) CREATE FUNCTION seg_contains(seg, seg)
RETURNS bool RETURNS bool
AS 'MODULE_PATHNAME' AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict); LANGUAGE 'C' STRICT IMMUTABLE;
COMMENT ON FUNCTION seg_contains(seg, seg) IS COMMENT ON FUNCTION seg_contains(seg, seg) IS
'contains'; 'contains';
@ -107,7 +107,7 @@ COMMENT ON FUNCTION seg_contains(seg, seg) IS
CREATE FUNCTION seg_contained(seg, seg) CREATE FUNCTION seg_contained(seg, seg)
RETURNS bool RETURNS bool
AS 'MODULE_PATHNAME' AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict); LANGUAGE 'C' STRICT IMMUTABLE;
COMMENT ON FUNCTION seg_contained(seg, seg) IS COMMENT ON FUNCTION seg_contained(seg, seg) IS
'contained in'; 'contained in';
@ -115,7 +115,7 @@ COMMENT ON FUNCTION seg_contained(seg, seg) IS
CREATE FUNCTION seg_overlap(seg, seg) CREATE FUNCTION seg_overlap(seg, seg)
RETURNS bool RETURNS bool
AS 'MODULE_PATHNAME' AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict); LANGUAGE 'C' STRICT IMMUTABLE;
COMMENT ON FUNCTION seg_overlap(seg, seg) IS COMMENT ON FUNCTION seg_overlap(seg, seg) IS
'overlaps'; 'overlaps';
@ -123,7 +123,7 @@ COMMENT ON FUNCTION seg_overlap(seg, seg) IS
CREATE FUNCTION seg_same(seg, seg) CREATE FUNCTION seg_same(seg, seg)
RETURNS bool RETURNS bool
AS 'MODULE_PATHNAME' AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict); LANGUAGE 'C' STRICT IMMUTABLE;
COMMENT ON FUNCTION seg_same(seg, seg) IS COMMENT ON FUNCTION seg_same(seg, seg) IS
'same as'; 'same as';
@ -131,7 +131,7 @@ COMMENT ON FUNCTION seg_same(seg, seg) IS
CREATE FUNCTION seg_different(seg, seg) CREATE FUNCTION seg_different(seg, seg)
RETURNS bool RETURNS bool
AS 'MODULE_PATHNAME' AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict); LANGUAGE 'C' STRICT IMMUTABLE;
COMMENT ON FUNCTION seg_different(seg, seg) IS COMMENT ON FUNCTION seg_different(seg, seg) IS
'different'; 'different';
@ -141,36 +141,36 @@ COMMENT ON FUNCTION seg_different(seg, seg) IS
CREATE OR REPLACE FUNCTION seg_cmp(seg, seg) CREATE OR REPLACE FUNCTION seg_cmp(seg, seg)
RETURNS int4 RETURNS int4
AS 'MODULE_PATHNAME' AS 'MODULE_PATHNAME'
LANGUAGE 'C' STRICT; LANGUAGE 'C' STRICT IMMUTABLE;
COMMENT ON FUNCTION seg_cmp(seg, seg) IS 'btree comparison function'; COMMENT ON FUNCTION seg_cmp(seg, seg) IS 'btree comparison function';
CREATE FUNCTION seg_union(seg, seg) CREATE FUNCTION seg_union(seg, seg)
RETURNS seg RETURNS seg
AS 'MODULE_PATHNAME' AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict); LANGUAGE 'C' STRICT IMMUTABLE;
CREATE FUNCTION seg_inter(seg, seg) CREATE FUNCTION seg_inter(seg, seg)
RETURNS seg RETURNS seg
AS 'MODULE_PATHNAME' AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict); LANGUAGE 'C' STRICT IMMUTABLE;
CREATE FUNCTION seg_size(seg) CREATE FUNCTION seg_size(seg)
RETURNS float4 RETURNS float4
AS 'MODULE_PATHNAME' AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict); LANGUAGE 'C' STRICT IMMUTABLE;
-- miscellaneous -- miscellaneous
CREATE FUNCTION seg_upper(seg) CREATE FUNCTION seg_upper(seg)
RETURNS float4 RETURNS float4
AS 'MODULE_PATHNAME' AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict); LANGUAGE 'C' STRICT IMMUTABLE;
CREATE FUNCTION seg_lower(seg) CREATE FUNCTION seg_lower(seg)
RETURNS float4 RETURNS float4
AS 'MODULE_PATHNAME' AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict); LANGUAGE 'C' STRICT IMMUTABLE;
-- --
@ -230,7 +230,6 @@ CREATE OPERATOR &< (
LEFTARG = seg, LEFTARG = seg,
RIGHTARG = seg, RIGHTARG = seg,
PROCEDURE = seg_over_left, PROCEDURE = seg_over_left,
COMMUTATOR = '&>',
RESTRICT = positionsel, RESTRICT = positionsel,
JOIN = positionjoinsel JOIN = positionjoinsel
); );
@ -240,15 +239,14 @@ CREATE OPERATOR && (
RIGHTARG = seg, RIGHTARG = seg,
PROCEDURE = seg_overlap, PROCEDURE = seg_overlap,
COMMUTATOR = '&&', COMMUTATOR = '&&',
RESTRICT = positionsel, RESTRICT = areasel,
JOIN = positionjoinsel JOIN = areajoinsel
); );
CREATE OPERATOR &> ( CREATE OPERATOR &> (
LEFTARG = seg, LEFTARG = seg,
RIGHTARG = seg, RIGHTARG = seg,
PROCEDURE = seg_over_right, PROCEDURE = seg_over_right,
COMMUTATOR = '&<',
RESTRICT = positionsel, RESTRICT = positionsel,
JOIN = positionjoinsel JOIN = positionjoinsel
); );
@ -321,7 +319,7 @@ LANGUAGE 'C';
CREATE FUNCTION gseg_penalty(internal,internal,internal) CREATE FUNCTION gseg_penalty(internal,internal,internal)
RETURNS internal RETURNS internal
AS 'MODULE_PATHNAME' AS 'MODULE_PATHNAME'
LANGUAGE 'C' with (isstrict); LANGUAGE 'C' STRICT;
CREATE FUNCTION gseg_picksplit(internal, internal) CREATE FUNCTION gseg_picksplit(internal, internal)
RETURNS internal RETURNS internal