Skip to content

Commit

Permalink
Spatial: Translate InteriorPoint, Union (unary), and IsWithinDistance
Browse files Browse the repository at this point in the history
Fixes #13281
  • Loading branch information
bricelam committed Oct 2, 2018
1 parent badbad7 commit b969be3
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 0 deletions.
43 changes: 43 additions & 0 deletions src/EFCore.Specification.Tests/Query/SpatialQueryTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,20 @@ public virtual Task GetPointN(bool isAsync)
es => es.Select(e => new { e.Id, Point0 = e.LineString.GetPointN(0) }));
}

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task InteriorPoint(bool isAsync)
{
return AssertQuery<PolygonEntity>(
isAsync,
es => es.Select(e => new { e.Id, e.Polygon.InteriorPoint, e.Polygon }),
elementAsserter: (e, a) =>
{
Assert.Equal(e.Id, a.Id);
Assert.True(a.Polygon.Contains(e.InteriorPoint));
});
}

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Intersection(bool isAsync)
Expand Down Expand Up @@ -477,6 +491,26 @@ public virtual Task IsValid(bool isAsync)
return AssertQuery<PointEntity>(isAsync, es => es.Select(e => new { e.Id, e.Point.IsValid }));
}

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task IsWithinDistance(bool isAsync)
{
var point = Fixture.GeometryFactory.CreatePoint(new Coordinate(0, 1));

return AssertQuery<PointEntity>(
isAsync,
es => es.Select(e => new { e.Id, IsWithinDistance = e.Point.IsWithinDistance(point, 1) }),
elementAsserter: (e, a) =>
{
Assert.Equal(e.Id, a.Id);

if (AssertDistances)
{
Assert.Equal(e.IsWithinDistance, a.IsWithinDistance);
}
});
}

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Item(bool isAsync)
Expand Down Expand Up @@ -736,6 +770,15 @@ public virtual Task Union(bool isAsync)
});
}

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Union_void(bool isAsync)
{
return AssertQuery<MultiLineStringEntity>(
isAsync,
es => es.Select(e => new { e.Id, Union = e.MultiLineString.Union() }));
}

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Within(bool isAsync)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public class SqlServerGeometryMemberTranslator : IMemberTranslator
{ typeof(IGeometry).GetRuntimeProperty(nameof(IGeometry.Boundary)), "STBoundary" },
{ typeof(IGeometry).GetRuntimeProperty(nameof(IGeometry.Centroid)), "STCentroid" },
{ typeof(IGeometry).GetRuntimeProperty(nameof(IGeometry.Envelope)), "STEnvelope" },
{ typeof(IGeometry).GetRuntimeProperty(nameof(IGeometry.InteriorPoint)), "STPointOnSurface" },
{ typeof(IGeometry).GetRuntimeProperty(nameof(IGeometry.IsSimple)), "STIsSimple" },
{ typeof(IGeometry).GetRuntimeProperty(nameof(IGeometry.PointOnSurface)), "STPointOnSurface" }
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public class SqlServerGeometryMethodTranslator : IMethodCallTranslator
};

private static readonly MethodInfo _getGeometryN = typeof(IGeometry).GetRuntimeMethod(nameof(IGeometry.GetGeometryN), new[] { typeof(int) });
private static readonly MethodInfo _isWithinDistance = typeof(IGeometry).GetRuntimeMethod(nameof(IGeometry.IsWithinDistance), new[] { typeof(IGeometry), typeof(double) });

/// <summary>
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
Expand Down Expand Up @@ -79,6 +80,16 @@ public virtual Expression Translate(MethodCallExpression methodCallExpression)
methodCallExpression.Type,
new[] { Expression.Add(methodCallExpression.Arguments[0], Expression.Constant(1)) });
}
if (Equals(method, _isWithinDistance))
{
return Expression.LessThanOrEqual(
new SqlFunctionExpression(
instance,
"STDistance",
typeof(double),
new[] { methodCallExpression.Arguments[0] }),
methodCallExpression.Arguments[1]);
}

return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,18 @@ public SqliteQuerySqlGenerator(
{
}

/// <summary>
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
protected override string TypedTrueLiteral => "1";

/// <summary>
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
protected override string TypedFalseLiteral => "0";

/// <summary>
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public class SqliteGeometryMemberTranslator : IMemberTranslator
{ typeof(IGeometry).GetRuntimeProperty(nameof(IGeometry.Centroid)), "Centroid" },
{ typeof(IGeometry).GetRuntimeProperty(nameof(IGeometry.Dimension)), "Dimension" },
{ typeof(IGeometry).GetRuntimeProperty(nameof(IGeometry.Envelope)), "Envelope" },
{ typeof(IGeometry).GetRuntimeProperty(nameof(IGeometry.InteriorPoint)), "PointOnSurface" },
{ typeof(IGeometry).GetRuntimeProperty(nameof(IGeometry.IsEmpty)), "IsEmpty" },
{ typeof(IGeometry).GetRuntimeProperty(nameof(IGeometry.IsSimple)), "IsSimple" },
{ typeof(IGeometry).GetRuntimeProperty(nameof(IGeometry.IsValid)), "IsValid" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,13 @@ public class SqliteGeometryMethodTranslator : IMethodCallTranslator
{ typeof(Geometry).GetRuntimeMethod(nameof(Geometry.ToBinary), Type.EmptyTypes), "AsBinary" },
{ typeof(Geometry).GetRuntimeMethod(nameof(Geometry.ToText), Type.EmptyTypes), "AsText" },
{ typeof(IGeometry).GetRuntimeMethod(nameof(IGeometry.Touches), new[] { typeof(IGeometry) }), "Touches" },
{ typeof(IGeometry).GetRuntimeMethod(nameof(IGeometry.Union), Type.EmptyTypes), "UnaryUnion" },
{ typeof(IGeometry).GetRuntimeMethod(nameof(IGeometry.Union), new[] { typeof(IGeometry) }), "GUnion" },
{ typeof(IGeometry).GetRuntimeMethod(nameof(IGeometry.Within), new[] { typeof(IGeometry) }), "Within" }
};

private static readonly MethodInfo _getGeometryN = typeof(IGeometry).GetRuntimeMethod(nameof(IGeometry.GetGeometryN), new[] { typeof(int) });
private static readonly MethodInfo _isWithinDistance = typeof(IGeometry).GetRuntimeMethod(nameof(IGeometry.IsWithinDistance), new[] { typeof(IGeometry), typeof(double) });

/// <summary>
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
Expand All @@ -74,6 +76,15 @@ public Expression Translate(MethodCallExpression methodCallExpression)
Expression.Add(methodCallExpression.Arguments[0], Expression.Constant(1))
});
}
if (Equals(method, _isWithinDistance))
{
return Expression.LessThanOrEqual(
new SqlFunctionExpression(
"Distance",
typeof(double),
new[] { methodCallExpression.Object, methodCallExpression.Arguments[0] }),
methodCallExpression.Arguments[1]);
}

return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,20 @@ public override async Task IsValid(bool isAsync)
FROM [PointEntity] AS [e]");
}

public override async Task IsWithinDistance(bool isAsync)
{
await base.IsWithinDistance(isAsync);

AssertSql(
@"@__point_0='0xE6100000010C000000000000F03F0000000000000000' (Size = 22) (DbType = Binary)
SELECT [e].[Id], CASE
WHEN [e].[Point].STDistance(@__point_0) <= 1.0E0
THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
END AS [IsWithinDistance]
FROM [PointEntity] AS [e]");
}

public override async Task Item(bool isAsync)
{
await base.Item(isAsync);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,15 @@ public override async Task GetPointN(bool isAsync)
FROM [LineStringEntity] AS [e]");
}

public override async Task InteriorPoint(bool isAsync)
{
await base.InteriorPoint(isAsync);

AssertSql(
@"SELECT [e].[Id], [e].[Polygon].STPointOnSurface() AS [InteriorPoint], [e].[Polygon]
FROM [PolygonEntity] AS [e]");
}

public override async Task Intersection(bool isAsync)
{
await base.Intersection(isAsync);
Expand Down Expand Up @@ -319,6 +328,21 @@ public override async Task IsValid(bool isAsync)
FROM [PointEntity] AS [e]");
}

[ConditionalTheory(Skip = "Needs better argument type inference")]
public override async Task IsWithinDistance(bool isAsync)
{
await base.IsWithinDistance(isAsync);

AssertSql(
@"@__point_0='0x00000000010C0000000000000000000000000000F03F' (Size = 22) (DbType = Binary)
SELECT [e].[Id], CASE
WHEN [e].[Point].STDistance(@__point_0) <= 1.0E0
THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
END AS [IsWithinDistance]
FROM [PointEntity] AS [e]");
}

[ConditionalTheory(Skip = "Needs better result type inference")]
public override async Task Item(bool isAsync)
{
Expand Down
32 changes: 32 additions & 0 deletions test/EFCore.Sqlite.FunctionalTests/Query/SpatialQuerySqliteTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,15 @@ public override async Task GetPointN(bool isAsync)
FROM ""LineStringEntity"" AS ""e""");
}

public override async Task InteriorPoint(bool isAsync)
{
await base.InteriorPoint(isAsync);

AssertSql(
@"SELECT ""e"".""Id"", PointOnSurface(""e"".""Polygon"") AS ""InteriorPoint"", ""e"".""Polygon""
FROM ""PolygonEntity"" AS ""e""");
}

public override async Task Intersection(bool isAsync)
{
await base.Intersection(isAsync);
Expand Down Expand Up @@ -336,6 +345,20 @@ public override async Task IsValid(bool isAsync)
FROM ""PointEntity"" AS ""e""");
}

public override async Task IsWithinDistance(bool isAsync)
{
await base.IsWithinDistance(isAsync);

AssertSql(
@"@__point_0='0x0001000000000000000000000000000000000000F03F00000000000000000000...' (Size = 60) (DbType = String)
SELECT ""e"".""Id"", CASE
WHEN Distance(""e"".""Point"", @__point_0) <= 1.0
THEN 1 ELSE 0
END AS ""IsWithinDistance""
FROM ""PointEntity"" AS ""e""");
}

public override async Task Item(bool isAsync)
{
await base.Item(isAsync);
Expand Down Expand Up @@ -499,6 +522,15 @@ public override async Task Union(bool isAsync)
FROM ""PolygonEntity"" AS ""e""");
}

public override async Task Union_void(bool isAsync)
{
await base.Union_void(isAsync);

AssertSql(
@"SELECT ""e"".""Id"", UnaryUnion(""e"".""MultiLineString"") AS ""Union""
FROM ""MultiLineStringEntity"" AS ""e""");
}

public override async Task Within(bool isAsync)
{
await base.Within(isAsync);
Expand Down

0 comments on commit b969be3

Please sign in to comment.