diff --git a/community/values/src/main/java/org/neo4j/values/Comparison.java b/community/values/src/main/java/org/neo4j/values/Comparison.java index 1b34f4f176c89..cad64966d09fe 100644 --- a/community/values/src/main/java/org/neo4j/values/Comparison.java +++ b/community/values/src/main/java/org/neo4j/values/Comparison.java @@ -34,7 +34,6 @@ public int value() { return 1; } - }, EQUAL { @@ -43,7 +42,6 @@ public int value() { return 0; } - }, SMALLER_THAN { @@ -52,18 +50,10 @@ public int value() { return -1; } - }, - UNDEFINED - { - @Override - public int value() - { - throw new IllegalStateException( - "This value is undefined and can't handle primitive comparisons" ); - } - - }; + GREATER_THAN_AND_EQUAL, + SMALLER_THAN_AND_EQUAL, + UNDEFINED; /** * Integer representation of comparison @@ -76,7 +66,10 @@ public int value() * if equal. * @throws IllegalStateException if the result is undefined. */ - public abstract int value(); + public int value() + { + throw new IllegalStateException( "This value is undefined and can't handle primitive comparisons" ); + } /** * Maps an integer value to comparison result. diff --git a/community/values/src/main/java/org/neo4j/values/storable/PointValue.java b/community/values/src/main/java/org/neo4j/values/storable/PointValue.java index e880abe5a07e6..c2749435d0e6e 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/PointValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/PointValue.java @@ -167,26 +167,49 @@ Comparison unsafeTernaryCompareTo( Value otherValue ) return Comparison.UNDEFINED; } - int result = 0; + int eq = 0; + int gt = 0; + int lt = 0; for ( int i = 0; i < coordinate.length; i++ ) { int cmpVal = Double.compare( this.coordinate[i], other.coordinate[i] ); - if ( cmpVal == 0 && result != 0 ) + if ( cmpVal > 0 ) { - // Equal on one dimension, but not others, is not defined - return Comparison.UNDEFINED; + gt++; } - if ( cmpVal != result ) + else if ( cmpVal < 0 ) { - if ( (cmpVal < 0 && result > 0) || (cmpVal > 0 && result < 0) || (i > 0 && result == 0) ) - { - return Comparison.UNDEFINED; - } - result = cmpVal; + lt++; + } + else + { + eq++; } } - - return Comparison.from( result ); + if ( eq == coordinate.length ) + { + return Comparison.EQUAL; + } + else if ( gt == coordinate.length ) + { + return Comparison.GREATER_THAN; + } + else if ( lt == coordinate.length ) + { + return Comparison.SMALLER_THAN; + } + else if ( lt == 0 ) + { + return Comparison.GREATER_THAN_AND_EQUAL; + } + else if ( gt == 0 ) + { + return Comparison.SMALLER_THAN_AND_EQUAL; + } + else + { + return Comparison.UNDEFINED; + } } @Override @@ -279,40 +302,41 @@ public CRS getCRS() * @param includeUpper governs if the upper comparison should be inclusive * @return true if this value is within the described range */ - public boolean withinRange( PointValue lower, boolean includeLower, PointValue upper, boolean includeUpper ) + public Boolean withinRange( PointValue lower, boolean includeLower, PointValue upper, boolean includeUpper ) { if ( lower == null && upper == null ) { return true; } - if ( (lower != null) && (this.crs.getCode() != lower.crs.getCode() || this.coordinate.length != lower.coordinate.length) ) - { - return false; - } - if ( (upper != null) && (this.crs.getCode() != upper.crs.getCode() || this.coordinate.length != upper.coordinate.length) ) + + if ( lower != null ) { - return false; + Comparison comparison = this.unsafeTernaryCompareTo( lower ); + if ( comparison == Comparison.UNDEFINED ) + { + return null; + } + else if ( comparison == Comparison.SMALLER_THAN || comparison == Comparison.SMALLER_THAN_AND_EQUAL || + (comparison == Comparison.EQUAL || comparison == Comparison.GREATER_THAN_AND_EQUAL) && !includeLower ) + { + return false; + } } - for ( int i = 0; i < coordinate.length; i++ ) + if ( upper != null ) { - if ( lower != null ) + Comparison comparison = this.unsafeTernaryCompareTo( upper ); + if ( comparison == Comparison.UNDEFINED ) { - int cmpVal = Double.compare( this.coordinate[i], lower.coordinate[i] ); - if ( !includeLower && cmpVal == 0 || cmpVal < 0 ) - { - return false; - } + return null; } - if ( upper != null ) + else if ( comparison == Comparison.GREATER_THAN || comparison == Comparison.GREATER_THAN_AND_EQUAL || + (comparison == Comparison.EQUAL || comparison == Comparison.SMALLER_THAN_AND_EQUAL) && !includeUpper ) { - int cmpVal = Double.compare( this.coordinate[i], upper.coordinate[i] ); - if ( !includeUpper && cmpVal == 0 || cmpVal > 0 ) - { - return false; - } + return false; } } + return true; } diff --git a/community/values/src/test/java/org/neo4j/values/storable/PointTest.java b/community/values/src/test/java/org/neo4j/values/storable/PointTest.java index b41a650a47c5a..106d9d940fe2f 100644 --- a/community/values/src/test/java/org/neo4j/values/storable/PointTest.java +++ b/community/values/src/test/java/org/neo4j/values/storable/PointTest.java @@ -114,22 +114,91 @@ public void shouldTernaryCompareTwoPoints() equalTo( Comparison.UNDEFINED ) ); assertThat( "Point greater on both dimensions is greater", pointValue( Cartesian, 2, 3 ).unsafeTernaryCompareTo( pointValue( Cartesian, 1, 2 ) ), equalTo( Comparison.GREATER_THAN ) ); - assertThat( "Point greater on first dimensions is UNDEFINED", pointValue( Cartesian, 2, 2 ).unsafeTernaryCompareTo( pointValue( Cartesian, 1, 2 ) ), - equalTo( Comparison.UNDEFINED ) ); - assertThat( "Point greater on second dimensions is UNDEFINED", pointValue( Cartesian, 1, 3 ).unsafeTernaryCompareTo( pointValue( Cartesian, 1, 2 ) ), - equalTo( Comparison.UNDEFINED ) ); + assertThat( "Point greater on first dimensions is >=", pointValue( Cartesian, 2, 2 ).unsafeTernaryCompareTo( pointValue( Cartesian, 1, 2 ) ), + equalTo( Comparison.GREATER_THAN_AND_EQUAL ) ); + assertThat( "Point greater on second dimensions is >=", pointValue( Cartesian, 1, 3 ).unsafeTernaryCompareTo( pointValue( Cartesian, 1, 2 ) ), + equalTo( Comparison.GREATER_THAN_AND_EQUAL ) ); assertThat( "Point smaller on both dimensions is smaller", pointValue( Cartesian, 0, 1 ).unsafeTernaryCompareTo( pointValue( Cartesian, 1, 2 ) ), equalTo( Comparison.SMALLER_THAN ) ); - assertThat( "Point smaller on first dimensions is UNDEFINED", pointValue( Cartesian, 0, 2 ).unsafeTernaryCompareTo( pointValue( Cartesian, 1, 2 ) ), - equalTo( Comparison.UNDEFINED ) ); - assertThat( "Point smaller on second dimensions is UNDEFINED", pointValue( Cartesian, 1, 1 ).unsafeTernaryCompareTo( pointValue( Cartesian, 1, 2 ) ), - equalTo( Comparison.UNDEFINED ) ); + assertThat( "Point smaller on first dimensions is <=", pointValue( Cartesian, 0, 2 ).unsafeTernaryCompareTo( pointValue( Cartesian, 1, 2 ) ), + equalTo( Comparison.SMALLER_THAN_AND_EQUAL ) ); + assertThat( "Point smaller on second dimensions is <=", pointValue( Cartesian, 1, 1 ).unsafeTernaryCompareTo( pointValue( Cartesian, 1, 2 ) ), + equalTo( Comparison.SMALLER_THAN_AND_EQUAL ) ); assertThat( "Point greater on first and smaller on second dimensions is UNDEFINED", pointValue( Cartesian, 2, 1 ).unsafeTernaryCompareTo( pointValue( Cartesian, 1, 2 ) ), equalTo( Comparison.UNDEFINED ) ); assertThat( "Point smaller on first and greater on second dimensions is UNDEFINED", pointValue( Cartesian, 0, 3 ).unsafeTernaryCompareTo( pointValue( Cartesian, 1, 2 ) ), equalTo( Comparison.UNDEFINED ) ); } + @Test + public void shouldComparePointWithin() + { + // Edge cases + assertThat( "Always within no bounds", pointValue( Cartesian, 1, 2 ).withinRange( null, false, null, false ), equalTo( true ) ); + assertThat( "Different CRS for lower bound should be undefined", + pointValue( Cartesian, 1, 2 ).withinRange( pointValue( WGS84, 1, 2 ), true, null, false ), equalTo( null ) ); + assertThat( "Different CRS for upper bound should be undefined", + pointValue( Cartesian, 1, 2 ).withinRange( null, false, pointValue( WGS84, 1, 2 ), true ), equalTo( null ) ); + + // Lower bound + assertThat( "Within same lower bound if inclusive", pointValue( Cartesian, 1, 2 ).withinRange( pointValue( Cartesian, 1, 2 ), true, null, false ), + equalTo( true ) ); + assertThat( "Not within same lower bound if not inclusive", + pointValue( Cartesian, 1, 2 ).withinRange( pointValue( Cartesian, 1, 2 ), false, null, false ), equalTo( false ) ); + assertThat( "Within smaller lower bound if inclusive", pointValue( Cartesian, 1, 2 ).withinRange( pointValue( Cartesian, 0, 1 ), true, null, false ), + equalTo( true ) ); + assertThat( "Within smaller lower bound if not inclusive", + pointValue( Cartesian, 1, 2 ).withinRange( pointValue( Cartesian, 0, 1 ), false, null, false ), equalTo( true ) ); + assertThat( "Within partially smaller lower bound if inclusive", + pointValue( Cartesian, 1, 2 ).withinRange( pointValue( Cartesian, 1, 1 ), true, null, false ), equalTo( true ) ); + assertThat( "Not within partially smaller lower bound if not inclusive", + pointValue( Cartesian, 1, 2 ).withinRange( pointValue( Cartesian, 1, 1 ), false, null, false ), equalTo( false ) ); + assertThat( "Invalid if lower bound both greater and less than", + pointValue( Cartesian, 1, 2 ).withinRange( pointValue( Cartesian, 2, 1 ), false, null, false ), equalTo( null ) ); + assertThat( "Invalid if lower bound both greater and less than even when inclusive", + pointValue( Cartesian, 1, 2 ).withinRange( pointValue( Cartesian, 2, 1 ), true, null, false ), equalTo( null ) ); + + // Upper bound + assertThat( "Within same upper bound if inclusive", pointValue( Cartesian, 1, 2 ).withinRange( null, false, pointValue( Cartesian, 1, 2 ), true ), + equalTo( true ) ); + assertThat( "Not within same upper bound if not inclusive", + pointValue( Cartesian, 1, 2 ).withinRange( null, false, pointValue( Cartesian, 1, 2 ), false ), equalTo( false ) ); + assertThat( "Within larger upper bound if inclusive", pointValue( Cartesian, 1, 2 ).withinRange( null, false, pointValue( Cartesian, 2, 3 ), true ), + equalTo( true ) ); + assertThat( "Within larger upper bound if not inclusive", + pointValue( Cartesian, 1, 2 ).withinRange( null, false, pointValue( Cartesian, 2, 3 ), false ), equalTo( true ) ); + assertThat( "Within partially larger upper bound if inclusive", + pointValue( Cartesian, 1, 2 ).withinRange( null, false, pointValue( Cartesian, 2, 2 ), true ), equalTo( true ) ); + assertThat( "Not within partially larger upper bound if not inclusive", + pointValue( Cartesian, 1, 2 ).withinRange( null, false, pointValue( Cartesian, 2, 2 ), false ), equalTo( false ) ); + assertThat( "Invalid if upper bound both greater and less than", + pointValue( Cartesian, 1, 2 ).withinRange( null, false, pointValue( Cartesian, 2, 1 ), false ), equalTo( null ) ); + assertThat( "Invalid if upper bound both greater and less than even when inclusive", + pointValue( Cartesian, 1, 2 ).withinRange( null, false, pointValue( Cartesian, 2, 1 ), true ), equalTo( null ) ); + + // Lower and upper bounds + assertThat( "Not within same bounds if inclusive on lower", pointValue( Cartesian, 1, 2 ).withinRange( pointValue( Cartesian, 1, 2 ), true, pointValue( Cartesian, 1, 2 ), false ), + equalTo( false ) ); + assertThat( "Not within same bounds if inclusive on upper", pointValue( Cartesian, 1, 2 ).withinRange( pointValue( Cartesian, 1, 2 ), false, pointValue( Cartesian, 1, 2 ), true ), + equalTo( false ) ); + assertThat( "Within same bounds if inclusive on both", pointValue( Cartesian, 1, 2 ).withinRange( pointValue( Cartesian, 1, 2 ), true, pointValue( Cartesian, 1, 2 ), true ), + equalTo( true ) ); + assertThat( "Not within same bounds if not inclusive", + pointValue( Cartesian, 1, 2 ).withinRange( pointValue( Cartesian, 1, 2 ), false, pointValue( Cartesian, 1, 2 ), false ), equalTo( false ) ); + assertThat( "Within smaller lower bound if inclusive", pointValue( Cartesian, 1, 2 ).withinRange( pointValue( Cartesian, 0, 1 ), true, pointValue( Cartesian, 1, 2 ), true ), + equalTo( true ) ); + assertThat( "Within smaller lower bound if inclusive on upper", pointValue( Cartesian, 1, 2 ).withinRange( pointValue( Cartesian, 0, 1 ), false, pointValue( Cartesian, 1, 2 ), true ), + equalTo( true ) ); + assertThat( "Not within smaller lower bound if not inclusive", + pointValue( Cartesian, 1, 2 ).withinRange( pointValue( Cartesian, 0, 1 ), false, pointValue( Cartesian, 1, 2 ), false ), equalTo( false ) ); + assertThat( "Within partially smaller lower bound if inclusive", + pointValue( Cartesian, 1, 2 ).withinRange( pointValue( Cartesian, 1, 1 ), true, pointValue( Cartesian, 2, 3 ), false ), equalTo( true ) ); + assertThat( "Not within partially smaller lower bound if not inclusive", + pointValue( Cartesian, 1, 2 ).withinRange( pointValue( Cartesian, 1, 1 ), false, pointValue( Cartesian, 2, 3 ), false ), equalTo( false ) ); + assertThat( "Within wider bounds", + pointValue( Cartesian, 1, 2 ).withinRange( pointValue( Cartesian, 0, 1 ), false, pointValue( Cartesian, 2, 3 ), false ), equalTo( true ) ); + } + //------------------------------------------------------------- // Parser tests diff --git a/enterprise/cypher/acceptance-spec-suite/src/test/scala/org/neo4j/internal/cypher/acceptance/SpatialFunctionsAcceptanceTest.scala b/enterprise/cypher/acceptance-spec-suite/src/test/scala/org/neo4j/internal/cypher/acceptance/SpatialFunctionsAcceptanceTest.scala index 1095c9ede6a5e..f4f2bd4c6ae3b 100644 --- a/enterprise/cypher/acceptance-spec-suite/src/test/scala/org/neo4j/internal/cypher/acceptance/SpatialFunctionsAcceptanceTest.scala +++ b/enterprise/cypher/acceptance-spec-suite/src/test/scala/org/neo4j/internal/cypher/acceptance/SpatialFunctionsAcceptanceTest.scala @@ -355,54 +355,54 @@ class SpatialFunctionsAcceptanceTest extends ExecutionEngineFunSuite with Cypher test("inequality on cartesian points") { // case same point - shouldCompareLike("point({x: 0, y: 0})", "point({x: 0, y: 0})", aBiggerB = false, aSmallerB = false) + shouldCompareLike("point({x: 0, y: 0})", "point({x: 0, y: 0})", a_GT_b = false, a_LT_b = false, a_GTEQ_b = true, a_LTEQ_b = true) // case top right quadrant - shouldCompareLike("point({x: 1, y: 1})", "point({x: 0, y: 0})", aBiggerB = true, aSmallerB = false) + shouldCompareLike("point({x: 1, y: 1})", "point({x: 0, y: 0})", a_GT_b = true, a_LT_b = false, a_GTEQ_b = true, a_LTEQ_b = false) // case bottom left quadrant - shouldCompareLike("point({x: -1, y: -1})", "point({x: 0, y: 0})", aBiggerB = false, aSmallerB = true) + shouldCompareLike("point({x: -1, y: -1})", "point({x: 0, y: 0})", a_GT_b = false, a_LT_b = true, a_GTEQ_b = false, a_LTEQ_b = true) // case top left quadrant - shouldCompareLike("point({x: -1, y: 1})", "point({x: 0, y: 0})", aBiggerB = null, aSmallerB = null) + shouldCompareLike("point({x: -1, y: 1})", "point({x: 0, y: 0})", a_GT_b = null, a_LT_b = null, a_GTEQ_b = null, a_LTEQ_b = null) // case bottom right quadrant - shouldCompareLike("point({x: 1, y: -1})", "point({x: 0, y: 0})", aBiggerB = null, aSmallerB = null) + shouldCompareLike("point({x: 1, y: -1})", "point({x: 0, y: 0})", a_GT_b = null, a_LT_b = null, a_GTEQ_b = null, a_LTEQ_b = null) // case straight top - shouldCompareLike("point({x: 0, y: 1})", "point({x: 0, y: 0})", aBiggerB = true, aSmallerB = false) + shouldCompareLike("point({x: 0, y: 1})", "point({x: 0, y: 0})", a_GT_b = false, a_LT_b = false, a_GTEQ_b = true, a_LTEQ_b = false) // case straight right - shouldCompareLike("point({x: 1, y: 0})", "point({x: 0, y: 0})", aBiggerB = true, aSmallerB = false) + shouldCompareLike("point({x: 1, y: 0})", "point({x: 0, y: 0})", a_GT_b = false, a_LT_b = false, a_GTEQ_b = true, a_LTEQ_b = false) // case straight bottom - shouldCompareLike("point({x: 0, y: -1})", "point({x: 0, y: 0})", aBiggerB = false, aSmallerB = true) + shouldCompareLike("point({x: 0, y: -1})", "point({x: 0, y: 0})", a_GT_b = false, a_LT_b = false, a_GTEQ_b = false, a_LTEQ_b = true) // case straight left - shouldCompareLike("point({x: -1, y: 0})", "point({x: 0, y: 0})", aBiggerB = false, aSmallerB = true) + shouldCompareLike("point({x: -1, y: 0})", "point({x: 0, y: 0})", a_GT_b = false, a_LT_b = false, a_GTEQ_b = false, a_LTEQ_b = true) } test("inequality on geographic points") { // case same point - shouldCompareLike("point({longitude: 0, latitude: 0})", "point({longitude: 0, latitude: 0})", aBiggerB = false, aSmallerB = false) + shouldCompareLike("point({longitude: 0, latitude: 0})", "point({longitude: 0, latitude: 0})", a_GT_b = false, a_LT_b = false, a_GTEQ_b = true, a_LTEQ_b = true) // case top right quadrant - shouldCompareLike("point({longitude: 1, latitude: 1})", "point({longitude: 0, latitude: 0})", aBiggerB = true, aSmallerB = false) + shouldCompareLike("point({longitude: 1, latitude: 1})", "point({longitude: 0, latitude: 0})", a_GT_b = true, a_LT_b = false, a_GTEQ_b = true, a_LTEQ_b = false) // case bottom left quadrant - shouldCompareLike("point({longitude: -1, latitude: -1})", "point({longitude: 0, latitude: 0})", aBiggerB = false, aSmallerB = true) + shouldCompareLike("point({longitude: -1, latitude: -1})", "point({longitude: 0, latitude: 0})", a_GT_b = false, a_LT_b = true, a_GTEQ_b = false, a_LTEQ_b = true) // case top left quadrant - shouldCompareLike("point({longitude: -1, latitude: 1})", "point({longitude: 0, latitude: 0})", aBiggerB = null, aSmallerB = null) + shouldCompareLike("point({longitude: -1, latitude: 1})", "point({longitude: 0, latitude: 0})", a_GT_b = null, a_LT_b = null, a_GTEQ_b = null, a_LTEQ_b = null) // case bottom right quadrant - shouldCompareLike("point({longitude: 1, latitude: -1})", "point({longitude: 0, latitude: 0})", aBiggerB = null, aSmallerB = null) + shouldCompareLike("point({longitude: 1, latitude: -1})", "point({longitude: 0, latitude: 0})", a_GT_b = null, a_LT_b = null, a_GTEQ_b = null, a_LTEQ_b = null) // case straight top - shouldCompareLike("point({longitude: 0, latitude: 1})", "point({longitude: 0, latitude: 0})", aBiggerB = true, aSmallerB = false) + shouldCompareLike("point({longitude: 0, latitude: 1})", "point({longitude: 0, latitude: 0})", a_GT_b = false, a_LT_b = false, a_GTEQ_b = true, a_LTEQ_b = false) // case straight right - shouldCompareLike("point({longitude: 1, latitude: 0})", "point({longitude: 0, latitude: 0})", aBiggerB = true, aSmallerB = false) + shouldCompareLike("point({longitude: 1, latitude: 0})", "point({longitude: 0, latitude: 0})", a_GT_b = false, a_LT_b = false, a_GTEQ_b = true, a_LTEQ_b = false) // case straight bottom - shouldCompareLike("point({longitude: 0, latitude: -1})", "point({longitude: 0, latitude: 0})", aBiggerB = false, aSmallerB = true) + shouldCompareLike("point({longitude: 0, latitude: -1})", "point({longitude: 0, latitude: 0})", a_GT_b = false, a_LT_b = false, a_GTEQ_b = false, a_LTEQ_b = true) // case straight left - shouldCompareLike("point({longitude: -1, latitude: 0})", "point({longitude: 0, latitude: 0})", aBiggerB = false, aSmallerB = true) + shouldCompareLike("point({longitude: -1, latitude: 0})", "point({longitude: 0, latitude: 0})", a_GT_b = false, a_LT_b = false, a_GTEQ_b = false, a_LTEQ_b = true) // the poles might be the same point, but in the effective projection onto 2D plane, they are not the same - shouldCompareLike("point({longitude: -1, latitude: 90})", "point({longitude: 1, latitude: 90})", aBiggerB = false, aSmallerB = true) - shouldCompareLike("point({longitude: 1, latitude: 90})", "point({longitude: -1, latitude: 90})", aBiggerB = true, aSmallerB = false) - shouldCompareLike("point({longitude: -1, latitude: -90})", "point({longitude: 1, latitude: -90})", aBiggerB = false, aSmallerB = true) - shouldCompareLike("point({longitude: 1, latitude: -90})", "point({longitude: -1, latitude: -90})", aBiggerB = true, aSmallerB = false) + shouldCompareLike("point({longitude: -1, latitude: 90})", "point({longitude: 1, latitude: 90})", a_GT_b = false, a_LT_b = false, a_GTEQ_b = false, a_LTEQ_b = true) + shouldCompareLike("point({longitude: 1, latitude: 90})", "point({longitude: -1, latitude: 90})", a_GT_b = false, a_LT_b = false, a_GTEQ_b = true, a_LTEQ_b = false) + shouldCompareLike("point({longitude: -1, latitude: -90})", "point({longitude: 1, latitude: -90})", a_GT_b = false, a_LT_b = false, a_GTEQ_b = false, a_LTEQ_b = true) + shouldCompareLike("point({longitude: 1, latitude: -90})", "point({longitude: -1, latitude: -90})", a_GT_b = false, a_LT_b = false, a_GTEQ_b = true, a_LTEQ_b = false) } test("inequality on 3D points") { @@ -410,17 +410,32 @@ class SpatialFunctionsAcceptanceTest extends ExecutionEngineFunSuite with Cypher (-1 to 1).foreach { x => (-1 to 1).foreach { y => (-1 to 1).foreach { z => - val same = x == 0 && y == 0 && z == 0 - val smaller = x <= 0 && y <= 0 && z <= 0 - val larger = x >= 0 && y >= 0 && z >= 0 + val same = Seq(x, y, z).forall(_ == 0) + val lteq = Seq(x, y, z).forall(_ <= 0) + val gteq = Seq(x, y, z).forall(_ >= 0) + val onAxis = Seq(x, y, z).contains(0) + val a = s"point({x: $x, y: $y, z: $z, crs: '$crsName'})" + val b = s"point({x: 0, y: 0, z: 0, crs: '$crsName'})" if (same) { - shouldCompareLike(s"point({x: $x, y: $y, z: $z, crs: '$crsName'})", s"point({x: 0, y: 0, z: 0, crs: '$crsName'})", aBiggerB = false, aSmallerB = false) - } else if (smaller) { - shouldCompareLike(s"point({x: $x, y: $y, z: $z, crs: '$crsName'})", s"point({x: 0, y: 0, z: 0, crs: '$crsName'})", aBiggerB = false, aSmallerB = true) - } else if (larger) { - shouldCompareLike(s"point({x: $x, y: $y, z: $z, crs: '$crsName'})", s"point({x: 0, y: 0, z: 0, crs: '$crsName'})", aBiggerB = true, aSmallerB = false) + shouldCompareLike(a, b, a_GT_b = false, a_LT_b = false, a_GTEQ_b = true, a_LTEQ_b = true) } else { - shouldCompareLike(s"point({x: $x, y: $y, z: $z, crs: '$crsName'})", s"point({x: 0, y: 0, z: 0, crs: '$crsName'})", aBiggerB = null, aSmallerB = null) + if (onAxis) { + if (lteq) { + shouldCompareLike(a, b, a_GT_b = false, a_LT_b = false, a_GTEQ_b = false, a_LTEQ_b = true) + } else if (gteq) { + shouldCompareLike(a, b, a_GT_b = false, a_LT_b = false, a_GTEQ_b = true, a_LTEQ_b = false) + } else { + shouldCompareLike(a, b, a_GT_b = null, a_LT_b = null, a_GTEQ_b = null, a_LTEQ_b = null) + } + } else { + if (lteq) { + shouldCompareLike(a, b, a_GT_b = false, a_LT_b = true, a_GTEQ_b = false, a_LTEQ_b = true) + } else if (gteq) { + shouldCompareLike(a, b, a_GT_b = true, a_LT_b = false, a_GTEQ_b = true, a_LTEQ_b = false) + } else { + shouldCompareLike(a, b, a_GT_b = null, a_LT_b = null, a_GTEQ_b = null, a_LTEQ_b = null) + } + } } } } @@ -429,18 +444,18 @@ class SpatialFunctionsAcceptanceTest extends ExecutionEngineFunSuite with Cypher } test("inequality on mixed points") { - shouldCompareLike("point({longitude: 0, latitude: 0})", "point({x: 0, y: 0})", aBiggerB = null, aSmallerB = null) + shouldCompareLike("point({longitude: 0, latitude: 0})", "point({x: 0, y: 0})", a_GT_b = null, a_LT_b = null, a_GTEQ_b = null, a_LTEQ_b = null) } - private def shouldCompareLike(a: String, b: String, aBiggerB: Any, aSmallerB: Any) = { + private def shouldCompareLike(a: String, b: String, a_GT_b: Any, a_LT_b: Any, a_GTEQ_b: Any, a_LTEQ_b: Any) = { val query = s"""WITH $a as a, $b as b - |RETURN a > b, a < b + |RETURN a > b, a < b, a >= b, a <= b """.stripMargin val result = executeWith(equalityAndLatestPointConfig, query).toList withClue(s"Comparing '$a' to '$b'") { - result should equal(List(Map("a > b" -> aBiggerB, "a < b" -> aSmallerB))) + result should equal(List(Map("a > b" -> a_GT_b, "a < b" -> a_LT_b, "a >= b" -> a_GTEQ_b, "a <= b" -> a_LTEQ_b))) } }