Skip to content

Commit

Permalink
Query: Remove ReLinq dependency in Funcletizer
Browse files Browse the repository at this point in the history
Fixes #13524
Fixes #13549

Part of #12048
  • Loading branch information
smitpatel committed Nov 2, 2018
1 parent 8112ac1 commit fc7ad0f
Show file tree
Hide file tree
Showing 53 changed files with 1,422 additions and 1,084 deletions.
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<SignAssembly>True</SignAssembly>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<LangVersion>7.2</LangVersion>
<NoWarn>$(NoWarn);CA1032;CA1034;CA1052;CA1063;CA1815;CA1819;CA1822;CA2231</NoWarn>
<NoWarn>$(NoWarn);CS1591;CA1032;CA1034;CA1052;CA1063;CA1815;CA1819;CA1822;CA2231</NoWarn>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ public static IServiceCollection AddEntityFrameworkInMemoryDatabase([NotNull] th
.TryAdd<IQueryContextFactory, InMemoryQueryContextFactory>()
.TryAdd<IEntityQueryModelVisitorFactory, InMemoryQueryModelVisitorFactory>()
.TryAdd<IEntityQueryableExpressionVisitorFactory, InMemoryEntityQueryableExpressionVisitorFactory>()
.TryAdd<IEvaluatableExpressionFilter, EvaluatableExpressionFilter>()
.TryAdd<IConventionSetBuilder, InMemoryConventionSetBuilder>()
.TryAdd<ISingletonOptions, IInMemorySingletonOptions>(p => p.GetService<IInMemorySingletonOptions>())
.TryAdd<ITypeMappingSource, InMemoryTypeMappingSource>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
using Microsoft.EntityFrameworkCore.Update.Internal;
using Microsoft.EntityFrameworkCore.ValueGeneration;
using Microsoft.Extensions.DependencyInjection;
using Remotion.Linq.Parsing.ExpressionVisitors.TreeEvaluation;
using ReLinq = Remotion.Linq.Parsing.ExpressionVisitors.TreeEvaluation;

namespace Microsoft.EntityFrameworkCore.Infrastructure
{
Expand Down Expand Up @@ -173,6 +173,7 @@ public override EntityFrameworkServicesBuilder TryAddCoreServices()
TryAdd<IExpressionFragmentTranslator, RelationalCompositeExpressionFragmentTranslator>();
TryAdd<ISqlTranslatingExpressionVisitorFactory, SqlTranslatingExpressionVisitorFactory>();
TryAdd<INamedConnectionStringResolver, NamedConnectionStringResolver>();
TryAdd<ReLinq.IEvaluatableExpressionFilter, ReLinqRelationalEvaluatableExpressionFilter>();
TryAdd<IEvaluatableExpressionFilter, RelationalEvaluatableExpressionFilter>();
TryAdd<IRelationalTransactionFactory, RelationalTransactionFactory>();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Linq.Expressions;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Utilities;

namespace Microsoft.EntityFrameworkCore.Query.Internal
{
/// <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>
public class ReLinqRelationalEvaluatableExpressionFilter : ReLinqEvaluatableExpressionFilter
{
private readonly IModel _model;

/// <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>
public ReLinqRelationalEvaluatableExpressionFilter([NotNull] IModel model)
{
Check.NotNull(model, nameof(model));

_model = model;
}

/// <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>
public override bool IsEvaluatableMethodCall(MethodCallExpression methodCallExpression)
=> _model.Relational().FindDbFunction(methodCallExpression.Method) == null
&& base.IsEvaluatableMethodCall(methodCallExpression);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,27 @@

namespace Microsoft.EntityFrameworkCore.Query.Internal
{
/// <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>

public class RelationalEvaluatableExpressionFilter : EvaluatableExpressionFilter
{
private readonly IModel _model;

/// <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>
public RelationalEvaluatableExpressionFilter([NotNull] IModel model)
{
Check.NotNull(model, nameof(model));

_model = model;
}

/// <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>
public override bool IsEvaluatableMethodCall(MethodCallExpression methodCallExpression)
=> _model.Relational().FindDbFunction(methodCallExpression.Method) == null
&& base.IsEvaluatableMethodCall(methodCallExpression);
public override bool IsEvaluatableExpression(Expression expression)
{
if (expression is MethodCallExpression methodCallExpression
&& _model.Relational().FindDbFunction(methodCallExpression.Method) != null)
{
return false;
}

return base.IsEvaluatableExpression(expression);
}
}
}
4 changes: 3 additions & 1 deletion src/EFCore.Relational/Query/Sql/DefaultQuerySqlGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,8 @@ protected virtual void GenerateFromSql(
case ParameterExpression parameterExpression:
if (parameters.TryGetValue(parameterExpression.Name, out var parameterValue))
{
IsCacheable = false;

var argumentValuesFromParameter = (object[])parameterValue;

substitutions = new string[argumentValuesFromParameter.Length];
Expand Down Expand Up @@ -1785,7 +1787,7 @@ protected override Expression VisitParameter(ParameterExpression parameterExpres
if (typeMapping == null
|| (!typeMapping.ClrType.UnwrapNullableType().IsAssignableFrom(parameterType)
&& (parameterType.IsEnum
|| !typeof(IConvertible).IsAssignableFrom(parameterType))))
|| !typeof(IConvertible).IsAssignableFrom(parameterType))))
{
typeMapping = Dependencies.TypeMappingSource.GetMapping(parameterType);
}
Expand Down
4 changes: 2 additions & 2 deletions src/EFCore.Specification.Tests/BuiltInDataTypesTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public abstract class BuiltInDataTypesTestBase<TFixture> : IClassFixture<TFixtur
[Theory]
[InlineData(false)]
[InlineData(true)]
public async Task Can_filter_projection_with_captured_enum_variable(bool async)
public virtual async Task Can_filter_projection_with_captured_enum_variable(bool async)
{
using (var context = CreateContext())
{
Expand Down Expand Up @@ -56,7 +56,7 @@ public async Task Can_filter_projection_with_captured_enum_variable(bool async)
[Theory]
[InlineData(false)]
[InlineData(true)]
public async Task Can_filter_projection_with_inline_enum_variable(bool async)
public virtual async Task Can_filter_projection_with_inline_enum_variable(bool async)
{
using (var context = CreateContext())
{
Expand Down
43 changes: 37 additions & 6 deletions src/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3915,7 +3915,7 @@ public virtual void Comparing_two_collection_navigations_composite_key()
{
var query = from g1 in ctx.Gears
from g2 in ctx.Gears
// ReSharper disable once PossibleUnintendedReferenceComparison
// ReSharper disable once PossibleUnintendedReferenceComparison
where g1.Weapons == g2.Weapons
orderby g1.Nickname
select new
Expand Down Expand Up @@ -4402,9 +4402,9 @@ public virtual Task Correlated_collections_naked_navigation_with_ToList_followed
return AssertQueryScalar<Gear>(
isAsync,
gs => (from g in gs
where g.Nickname != "Marcus"
orderby g.Nickname
select g.Weapons.ToList()).Select(e => e.Count),
where g.Nickname != "Marcus"
orderby g.Nickname
select g.Weapons.ToList()).Select(e => e.Count),
assertOrder: true);
}

Expand Down Expand Up @@ -6820,7 +6820,7 @@ public virtual Task GroupBy_Property_Include_Select_Average(bool isAsync)
{
return AssertQueryScalar<Gear>(
isAsync,
gs => gs.Include(g => g.CityOfBirth ).GroupBy(g => g.Rank).Select(g => g.Average(gg => gg.SquadId)));
gs => gs.Include(g => g.CityOfBirth).GroupBy(g => g.Rank).Select(g => g.Average(gg => gg.SquadId)));
}

[ConditionalTheory]
Expand Down Expand Up @@ -7006,7 +7006,7 @@ public virtual Task Multiple_includes_with_client_method_around_qsre_and_also_pr
return Task.CompletedTask;
}

public TEntity Client<TEntity>(TEntity entity) => entity;
public TEntity Client<TEntity>(TEntity entity) => entity;

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
Expand Down Expand Up @@ -7152,6 +7152,37 @@ public virtual Task Null_semantics_is_correctly_applied_for_function_comparisons
ts => ts.Where(t => Maybe(t.Gear, () => t.Note.Substring(0, t.Gear.Squad.Name.Length)) == t.GearNickName));
}

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Filter_with_new_Guid(bool isAsync)
{
return AssertQuery<CogTag>(
isAsync,
ts => from t in ts
where t.Id == new Guid("DF36F493-463F-4123-83F9-6B135DEEB7BA")
select t);
}

public virtual async Task Filter_with_new_Guid_closure(bool isAsync)
{
var guid = "DF36F493-463F-4123-83F9-6B135DEEB7BD";

await AssertQuery<CogTag>(
isAsync,
ts => from t in ts
where t.Id == new Guid(guid)
select t);

guid = "B39A6FBA-9026-4D69-828E-FD7068673E57";

await AssertQuery<CogTag>(
isAsync,
ts => from t in ts
where t.Id == new Guid(guid)
select t);
}


protected GearsOfWarContext CreateContext() => Fixture.CreateContext();

protected virtual void ClearLog()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ public virtual void Extension_method_DbContext_property_chain_is_parameterized()
}
}

[Fact]
[Fact(Skip = "See issue#13587")]
public virtual void Using_DbSet_in_filter_works()
{
using (var context = CreateContext())
Expand All @@ -340,7 +340,7 @@ public virtual void Using_DbSet_in_filter_works()
}
}

[Fact]
[Fact(Skip = "See issue#13587")]
public virtual void Using_Context_set_method_in_filter_works()
{
using (var context = CreateContext())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public virtual void Auto_initialized_view_set()
}
}

[ConditionalFact]
[ConditionalFact(Skip = "See issue#13587")]
public virtual void QueryType_with_nav_defining_query()
{
using (var context = CreateContext())
Expand All @@ -81,7 +81,7 @@ var results
}
}

[Theory]
[Theory(Skip = "See issue#13587")]
[MemberData(nameof(IsAsyncData))]
public virtual Task QueryType_with_defining_query(bool isAsync)
{
Expand All @@ -100,7 +100,7 @@ public virtual Task QueryType_with_defining_query_and_correlated_collection(bool
ovs => ovs.Where(ov => ov.CustomerID == "ALFKI").Select(ov => ov.Customer).Select(cv => cv.Orders.Where(cc => true).ToList()));
}

[Theory]
[Theory(Skip = "See issue#13587")]
[MemberData(nameof(IsAsyncData))]
public virtual Task QueryType_with_mixed_tracking(bool isAsync)
{
Expand All @@ -117,7 +117,7 @@ from o in ovs.Where(ov => ov.CustomerID == c.CustomerID)
e => e.c.CustomerID);
}

[Theory]
[Theory(Skip = "See issue#13587")]
[MemberData(nameof(IsAsyncData))]
public virtual Task QueryType_with_included_nav(bool isAsync)
{
Expand All @@ -132,7 +132,7 @@ public virtual Task QueryType_with_included_nav(bool isAsync)
});
}

[Theory]
[Theory(Skip = "See issue#13587")]
[MemberData(nameof(IsAsyncData))]
public virtual Task QueryType_with_included_navs_multi_level(bool isAsync)
{
Expand All @@ -148,7 +148,7 @@ public virtual Task QueryType_with_included_navs_multi_level(bool isAsync)
});
}

[Theory]
[Theory(Skip = "See issue#13587")]
[MemberData(nameof(IsAsyncData))]
public virtual Task QueryType_select_where_navigation(bool isAsync)
{
Expand All @@ -159,7 +159,7 @@ public virtual Task QueryType_select_where_navigation(bool isAsync)
select ov);
}

[Theory]
[Theory(Skip = "See issue#13587")]
[MemberData(nameof(IsAsyncData))]
public virtual Task QueryType_select_where_navigation_multi_level(bool isAsync)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1199,6 +1199,49 @@ await AssertQuery<Customer>(
}.Contains(c.CustomerID)), entryCount: 1);
}

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual async Task Contains_with_local_non_primitive_list_inline_closure_mix(bool isAsync)
{
var id = "ALFKI";

await AssertQuery<Customer>(
isAsync,
cs => cs.Where(
c => new List<Customer>
{
new Customer{ CustomerID = "ABCDE" },
new Customer{ CustomerID = id }
}.Select(i => i.CustomerID).Contains(c.CustomerID)), entryCount: 1);

id = "ANATR";

await AssertQuery<Customer>(
isAsync,
cs => cs.Where(
c => new List<Customer>
{
new Customer{ CustomerID = "ABCDE" },
new Customer{ CustomerID = id }
}.Select(i => i.CustomerID).Contains(c.CustomerID)), entryCount: 1);
}

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual async Task Contains_with_local_non_primitive_list_closure_mix(bool isAsync)
{
var ids = new List<Customer>
{
new Customer{ CustomerID = "ABCDE" },
new Customer{ CustomerID = "ALFKI" }
};

await AssertQuery<Customer>(
isAsync,
cs => cs.Where(
c => ids.Select(i => i.CustomerID).Contains(c.CustomerID)), entryCount: 1);
}

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Contains_with_local_collection_false(bool isAsync)
Expand Down
Loading

0 comments on commit fc7ad0f

Please sign in to comment.