Skip to content

Commit

Permalink
Query: Improve parameterization of queryable functions
Browse files Browse the repository at this point in the history
Resolves #20162

- Never evaluate DbFunction
  - If it is inside lambda then we will have whole method call
  - If it is outside of lambda then it will be evaluated by compiler already
  • Loading branch information
smitpatel committed Mar 5, 2020
1 parent 2488830 commit 97e46ac
Show file tree
Hide file tree
Showing 6 changed files with 12 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,15 @@ public override bool IsEvaluatableExpression(Expression expression, IModel model
Check.NotNull(model, nameof(model));

if (expression is MethodCallExpression methodCallExpression
&& model.FindDbFunction(methodCallExpression.Method) is IDbFunction func)
&& model.FindDbFunction(methodCallExpression.Method) != null)
{
return func?.IsQueryable ?? true;
// Never evaluate DbFunction
// If it is inside lambda then we will have whole method call
// If it is outside of lambda then it will be evaluated for queryable function already.
return false;
}

return base.IsEvaluatableExpression(expression, model);
}

public override bool IsQueryableFunction(Expression expression, IModel model) =>
expression is MethodCallExpression methodCallExpression
&& model.FindDbFunction(methodCallExpression.Method)?.IsQueryable == true;
}
}
2 changes: 0 additions & 2 deletions src/EFCore/Query/EvaluatableExpressionFilterBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,5 @@ public virtual bool IsEvaluatableExpression(Expression expression, IModel model)

return true;
}

public virtual bool IsQueryableFunction(Expression expression, IModel model) => false;
}
}
8 changes: 0 additions & 8 deletions src/EFCore/Query/IEvaluatableExpressionFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,5 @@ public interface IEvaluatableExpressionFilter
/// <param name="model"> The model. </param>
/// <returns> True if the expression can be evaluated; false otherwise. </returns>
bool IsEvaluatableExpression([NotNull] Expression expression, [NotNull] IModel model);

/// <summary>
/// Checks whether the given expression is a queryable function
/// </summary>
/// <param name="expression"> The expression. </param>
/// <param name="model"> The model. </param>
/// <returns> True if the expression is a queryable function </returns>
bool IsQueryableFunction([NotNull] Expression expression, [NotNull] IModel model);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -552,12 +552,6 @@ protected override Expression VisitListInit(ListInitExpression listInitExpressio

protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression)
{
if (_evaluatableExpressionFilter.IsQueryableFunction(methodCallExpression, _model)
&& !_inLambda)
{
_evaluatable = false;
}

Visit(methodCallExpression.Object);
var parameterInfos = methodCallExpression.Method.GetParameters();
for (var i = 0; i < methodCallExpression.Arguments.Count; i++)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1545,7 +1545,7 @@ from r in context.GetCustomerOrderCountByYear(c.Id)
}
}

[ConditionalFact]
[ConditionalFact(Skip = "Issue#20184")]
public virtual void QF_Select_Direct_In_Anonymous()
{
using (var context = CreateContext())
Expand Down Expand Up @@ -1640,7 +1640,7 @@ select a.OrderId
}
}

[ConditionalFact]
[ConditionalFact(Skip = "Issue#20184")]
public virtual void QF_Select_Correlated_Subquery_In_Anonymous_Nested()
{
using (var context = CreateContext())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -639,11 +639,9 @@ public override void QF_CrossJoin_Not_Correlated()
base.QF_CrossJoin_Not_Correlated();

AssertSql(
@"@__customerId_1='2'
SELECT [c].[Id], [c].[LastName], [o].[Year], [o].[Count]
@"SELECT [c].[Id], [c].[LastName], [o].[Year], [o].[Count]
FROM [Customers] AS [c]
CROSS JOIN [dbo].[GetCustomerOrderCountByYear](@__customerId_1) AS [o]
CROSS JOIN [dbo].[GetCustomerOrderCountByYear](2) AS [o]
WHERE [c].[Id] = 2
ORDER BY [o].[Count]");
}
Expand All @@ -653,13 +651,12 @@ public override void QF_CrossJoin_Parameter()
base.QF_CrossJoin_Parameter();

AssertSql(
@"@__customerId_1='2'
@__custId_2='2'
@"@__custId_1='2'
SELECT [c].[Id], [c].[LastName], [o].[Year], [o].[Count]
FROM [Customers] AS [c]
CROSS JOIN [dbo].[GetCustomerOrderCountByYear](@__customerId_1) AS [o]
WHERE [c].[Id] = @__custId_2
CROSS JOIN [dbo].[GetCustomerOrderCountByYear](@__custId_1) AS [o]
WHERE [c].[Id] = @__custId_1
ORDER BY [o].[Count]");
}

Expand Down

0 comments on commit 97e46ac

Please sign in to comment.