Skip to content

Commit

Permalink
Handle spatial and temporal field-accessors in compiled runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
pontusmelke committed May 3, 2018
1 parent e81f092 commit fee00cf
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 16 deletions.
Expand Up @@ -49,6 +49,9 @@
import org.neo4j.values.SequenceValue;
import org.neo4j.values.storable.ArrayValue;
import org.neo4j.values.storable.BooleanValue;
import org.neo4j.values.storable.DurationValue;
import org.neo4j.values.storable.PointValue;
import org.neo4j.values.storable.TemporalValue;
import org.neo4j.values.storable.Values;
import org.neo4j.values.virtual.ListValue;
import org.neo4j.values.virtual.MapValue;
Expand Down Expand Up @@ -651,6 +654,19 @@ public static Object mapGetProperty( Object object, String key )
Map<String,Object> map = (Map<String,Object>) object;
return map.get( key );
}
if ( object instanceof TemporalValue<?,?> )
{
return ((TemporalValue<?,?>) object).get( key );
}
if ( object instanceof DurationValue )
{
return ((DurationValue) object).get( key );
}
if ( object instanceof PointValue )
{
return ((PointValue) object).get( key );
}

// NOTE: VirtualNodeValue and VirtualRelationshipValue will fall through to here
// To handle these we would need specialized cursor code
throw new CypherTypeException( String.format( "Type mismatch: expected a map but was %s", object ), null );
Expand Down
Expand Up @@ -418,7 +418,7 @@ else if ( crs == CoordinateReferenceSystem.WGS84_3D )
/**
* For accessors from cypher.
*/
public AnyValue get( String fieldName )
public Value get( String fieldName )
{
switch ( fieldName.toLowerCase() )
{
Expand Down
Expand Up @@ -588,35 +588,54 @@ class SpatialFunctionsAcceptanceTest extends ExecutionEngineFunSuite with Cypher
failWithError(equalityConfig + Configs.Procs, query, Seq("Collections containing point values with different CRS can not be stored in properties."))
}

// FIXME accessors should also work in compiled runtime. Split query into two so that compiled picks it up.
test("accessors on 2D cartesian points") {
val result = executeWith(latestPointConfig, "WITH point({x: 1, y: 2}) AS p RETURN p.x, p.y, p.crs, p.srid")
result.toList should be(List(Map("p.x" -> 1.0, "p.y" -> 2.0, "p.crs" -> "cartesian", "p.srid" -> 7203)))
// given
graph.execute("CREATE (:P {p : point({x: 1, y: 2})})")

// when
val result = executeWith(Configs.All - Configs.OldAndRule, "MATCH (n:P) WITH n.p AS p RETURN p.x, p.y, p.crs, p.srid")

failWithError(latestPointConfig + Configs.Procs, "WITH point({x: 1, y: 2}) AS p RETURN p.latitude", Seq("Field: latitude is not available"))
failWithError(latestPointConfig + Configs.Procs, "WITH point({x: 1, y: 2}) AS p RETURN p.z", Seq("Field: z is not available"))
// then
result.toList should be(List(Map("p.x" -> 1.0, "p.y" -> 2.0, "p.crs" -> "cartesian", "p.srid" -> 7203)))
failWithError(Configs.All - Configs.OldAndRule + Configs.Procs, "MATCH (n:P) WITH n.p AS p RETURN p.latitude", Seq("Field: latitude is not available"))
failWithError(Configs.All - Configs.OldAndRule + Configs.Procs, "MATCH (n:P) WITH n.p AS p RETURN p.z", Seq("Field: z is not available"))
}

test("accessors on 3D cartesian points") {
val result = executeWith(latestPointConfig, "WITH point({x: 1, y: 2, z:3}) AS p RETURN p.x, p.y, p.z, p.crs, p.srid")
result.toList should be(List(Map("p.x" -> 1.0, "p.y" -> 2.0, "p.z" -> 3.0, "p.crs" -> "cartesian-3d", "p.srid" -> 9157)))
// given
graph.execute("CREATE (:P {p : point({x: 1, y: 2, z:3})})")

// when
val result = executeWith(Configs.All - Configs.OldAndRule, "MATCH (n:P) WITH n.p AS p RETURN p.x, p.y, p.z, p.crs, p.srid")

failWithError(latestPointConfig + Configs.Procs, "WITH point({x: 1, y: 2, z:3}) AS p RETURN p.latitude", Seq("Field: latitude is not available"))
// then
result.toList should be(List(Map("p.x" -> 1.0, "p.y" -> 2.0, "p.z" -> 3.0, "p.crs" -> "cartesian-3d", "p.srid" -> 9157)))
failWithError(Configs.All - Configs.OldAndRule + Configs.Procs, "MATCH (n:P) WITH n.p AS p RETURN p.latitude", Seq("Field: latitude is not available"))
}

test("accessors on 2D geographic points") {
val result = executeWith(latestPointConfig, "WITH point({longitude: 1, latitude: 2}) AS p RETURN p.longitude, p.latitude, p.crs, p.x, p.y, p.srid")
result.toList should be(List(Map("p.longitude" -> 1.0, "p.latitude" -> 2.0, "p.crs" -> "wgs-84", "p.x" -> 1.0, "p.y" -> 2.0, "p.srid" -> 4326)))
// given
graph.execute("CREATE (:P {p : point({longitude: 1, latitude: 2})})")

// when
val result = executeWith(Configs.All - Configs.OldAndRule, "MATCH (n:P) WITH n.p AS p RETURN p.longitude, p.latitude, p.crs, p.x, p.y, p.srid")

failWithError(latestPointConfig + Configs.Procs, "WITH point({x: 1, y: 2}) AS p RETURN p.height", Seq("Field: height is not available"))
failWithError(latestPointConfig + Configs.Procs, "WITH point({x: 1, y: 2}) AS p RETURN p.z", Seq("Field: z is not available"))
// then
result.toList should be(List(Map("p.longitude" -> 1.0, "p.latitude" -> 2.0, "p.crs" -> "wgs-84", "p.x" -> 1.0, "p.y" -> 2.0, "p.srid" -> 4326)))
failWithError(Configs.All - Configs.OldAndRule + Configs.Procs, "MATCH (n:P) WITH n.p AS p RETURN p.height", Seq("Field: height is not available"))
failWithError(Configs.All - Configs.OldAndRule + Configs.Procs, "MATCH (n:P) WITH n.p AS p RETURN p.z", Seq("Field: z is not available"))
}

test("accessors on 3D geographic points") {
val result = executeWith(latestPointConfig,
"WITH point({longitude: 1, latitude: 2, height:3}) AS p RETURN p.longitude, p.latitude, p.height, p.crs, p.x, p.y, p.z, p.srid")
// given
graph.execute("CREATE (:P {p : point({longitude: 1, latitude: 2, height:3})})")

// when
val result = executeWith(Configs.All - Configs.OldAndRule,
"MATCH (n:P) WITH n.p AS p RETURN p.longitude, p.latitude, p.height, p.crs, p.x, p.y, p.z, p.srid")

// then
result.toList should be(List(Map("p.longitude" -> 1.0, "p.latitude" -> 2.0, "p.height" -> 3.0, "p.crs" -> "wgs-84-3d", "p.srid" -> 4979,
"p.x" -> 1.0, "p.y" -> 2.0, "p.z" -> 3.0)))
}

}

0 comments on commit fee00cf

Please sign in to comment.