Skip to content

Commit 739ce82

Browse files
committed
Code review changes
1 parent 934e16c commit 739ce82

File tree

5 files changed

+73
-49
lines changed

5 files changed

+73
-49
lines changed

src/NHibernate.Test/Async/Linq/ParameterTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ public async Task UsingNegateValueTypeParameterAsync()
112112
var value = 1;
113113
await (AssertTotalParametersAsync(
114114
db.Orders.Where(o => o.OrderId == value && o.OrderId != -value),
115-
2));
115+
1));
116116
}
117117

118118
[Test]

src/NHibernate.Test/Linq/ParameterTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ public void UsingNegateValueTypeParameter()
120120
var value = 1;
121121
AssertTotalParameters(
122122
db.Orders.Where(o => o.OrderId == value && o.OrderId != -value),
123-
2);
123+
1);
124124
}
125125

126126
[Test]

src/NHibernate/Linq/ExpressionTransformers/RemoveCharToIntConversion.cs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,19 @@ public Expression Transform(BinaryExpression expression)
3535

3636
if (!lhsIsConvertExpression && !rhsIsConvertExpression) return expression;
3737

38+
// Variables are not converted to constants (E.g: o.CharProperty == charVariable)
39+
if (lhsIsConvertExpression && rhsIsConvertExpression)
40+
{
41+
var lhsConvertExpression = (UnaryExpression) lhs;
42+
var rhsConvertExpression = (UnaryExpression) rhs;
43+
if (!IsConvertCharToInt(lhsConvertExpression) || !IsConvertCharToInt(rhsConvertExpression))
44+
{
45+
return expression;
46+
}
47+
48+
return Expression.MakeBinary(expression.NodeType, lhsConvertExpression.Operand, rhsConvertExpression.Operand);
49+
}
50+
3851
var lhsIsConstantExpression = IsConstantExpression(lhs);
3952
var rhsIsConstantExpression = IsConstantExpression(rhs);
4053

@@ -43,7 +56,7 @@ public Expression Transform(BinaryExpression expression)
4356
var convertExpression = lhsIsConvertExpression ? (UnaryExpression)lhs : (UnaryExpression)rhs;
4457
var constantExpression = lhsIsConstantExpression ? (ConstantExpression)lhs : (ConstantExpression)rhs;
4558

46-
if (convertExpression.Type == typeof(int) && convertExpression.Operand.Type == typeof(char) && constantExpression.Type == typeof(int))
59+
if (IsConvertCharToInt(convertExpression) && constantExpression.Type == typeof(int))
4760
{
4861
var constant = Expression.Constant(Convert.ToChar((int)constantExpression.Value));
4962

@@ -56,6 +69,11 @@ public Expression Transform(BinaryExpression expression)
5669
return expression;
5770
}
5871

72+
private static bool IsConvertCharToInt(UnaryExpression expression)
73+
{
74+
return expression.Type == typeof(int) && expression.Operand.Type == typeof(char);
75+
}
76+
5977
private static bool IsConvertExpression(Expression expression)
6078
{
6179
return (expression.NodeType == ExpressionType.Convert);
@@ -71,4 +89,4 @@ public ExpressionType[] SupportedExpressionTypes
7189
get { return _supportedExpressionTypes; }
7290
}
7391
}
74-
}
92+
}

src/NHibernate/Linq/Visitors/NhPartialEvaluatingExpressionVisitor.cs

Lines changed: 7 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,8 @@
1616
//
1717

1818
using System;
19-
using System.Collections.Generic;
2019
using System.Linq;
2120
using System.Linq.Expressions;
22-
using System.Reflection;
23-
using System.Runtime.CompilerServices;
2421
using NHibernate.Collection;
2522
using NHibernate.Engine;
2623
using NHibernate.Linq.Functions;
@@ -112,10 +109,10 @@ public override Expression Visit(Expression expression)
112109
// Variables in expressions are never a constant, they are encapsulated as fields of a compiler generated class.
113110
// Skip detecting variables for DML queries as HQL does not support reusing parameters for them.
114111
if (expression.NodeType != ExpressionType.Constant &&
115-
_preTransformationParameters.QueryMode == QueryMode.Select &&
112+
_preTransformationParameters.QueryMode == QueryMode.Select &&
116113
evaluatedExpression is ConstantExpression variableConstant &&
117114
!_preTransformationParameters.QueryVariables.ContainsKey(variableConstant) &&
118-
IsVariable(expression, out var path, out var closureContext))
115+
ExpressionsHelper.IsVariable(expression, out var path, out var closureContext))
119116
{
120117
_preTransformationParameters.QueryVariables.Add(variableConstant, new QueryVariable(path, closureContext));
121118
}
@@ -163,46 +160,6 @@ protected override Expression VisitConstant(ConstantExpression expression)
163160
}
164161
return base.VisitConstant(expression);
165162
}
166-
167-
private bool IsVariable(Expression expression, out string path, out object closureContext)
168-
{
169-
Expression childExpression;
170-
string currentPath;
171-
switch (expression)
172-
{
173-
case MemberExpression memberExpression:
174-
childExpression = memberExpression.Expression;
175-
currentPath = memberExpression.Member.Name;
176-
break;
177-
case ConstantExpression constantExpression:
178-
path = null;
179-
if (constantExpression.Type.Attributes.HasFlag(TypeAttributes.NestedPrivate) &&
180-
Attribute.IsDefined(constantExpression.Type, typeof(CompilerGeneratedAttribute), inherit: true))
181-
{
182-
closureContext = constantExpression.Value;
183-
return true;
184-
}
185-
186-
closureContext = null;
187-
return false;
188-
case UnaryExpression unaryExpression:
189-
childExpression = unaryExpression.Operand;
190-
currentPath = $"({unaryExpression.NodeType})";
191-
break;
192-
default:
193-
path = null;
194-
closureContext = null;
195-
return false;
196-
}
197-
198-
if (!IsVariable(childExpression, out path, out closureContext))
199-
{
200-
return false;
201-
}
202-
203-
path = path != null ? $"{path}_{currentPath}" : currentPath;
204-
return true;
205-
}
206163
}
207164

208165
internal struct QueryVariable : IEquatable<QueryVariable>
@@ -255,6 +212,11 @@ public override bool IsEvaluatableConstant(ConstantExpression node)
255212
return base.IsEvaluatableConstant(node);
256213
}
257214

215+
public override bool IsEvaluatableUnary(UnaryExpression node)
216+
{
217+
return !ExpressionsHelper.IsVariable(node.Operand, out _, out _);
218+
}
219+
258220
public override bool IsEvaluatableMember(MemberExpression node)
259221
{
260222
if (node == null)

src/NHibernate/Util/ExpressionsHelper.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Linq;
44
using System.Linq.Expressions;
55
using System.Reflection;
6+
using System.Runtime.CompilerServices;
67
using NHibernate.Engine;
78
using NHibernate.Linq;
89
using NHibernate.Linq.Expressions;
@@ -28,6 +29,49 @@ public static MemberInfo DecodeMemberAccessExpression<TEntity, TResult>(Expressi
2829
return ((MemberExpression)expression.Body).Member;
2930
}
3031

32+
/// <summary>
33+
/// Check whether the given expression represent a variable.
34+
/// </summary>
35+
/// <param name="expression">The expression to check.</param>
36+
/// <param name="path">The path of the variable.</param>
37+
/// <param name="closureContext">The closure context where the variable is stored.</param>
38+
/// <returns></returns>
39+
internal static bool IsVariable(Expression expression, out string path, out object closureContext)
40+
{
41+
Expression childExpression;
42+
string currentPath;
43+
switch (expression)
44+
{
45+
case MemberExpression memberExpression:
46+
childExpression = memberExpression.Expression;
47+
currentPath = memberExpression.Member.Name;
48+
break;
49+
case ConstantExpression constantExpression:
50+
path = null;
51+
if (constantExpression.Type.Attributes.HasFlag(TypeAttributes.NestedPrivate) &&
52+
Attribute.IsDefined(constantExpression.Type, typeof(CompilerGeneratedAttribute), inherit: true))
53+
{
54+
closureContext = constantExpression.Value;
55+
return true;
56+
}
57+
58+
closureContext = null;
59+
return false;
60+
default:
61+
path = null;
62+
closureContext = null;
63+
return false;
64+
}
65+
66+
if (!IsVariable(childExpression, out path, out closureContext))
67+
{
68+
return false;
69+
}
70+
71+
path = path != null ? $"{currentPath}_{path}" : currentPath;
72+
return true;
73+
}
74+
3175
/// <summary>
3276
/// Get the mapped type for the given expression.
3377
/// </summary>

0 commit comments

Comments
 (0)