Skip to content

Commit 60c77cb

Browse files
committed
NH-3647 Support Math.Round in QueryOver() projections.
1 parent e6e2583 commit 60c77cb

File tree

3 files changed

+85
-1
lines changed

3 files changed

+85
-1
lines changed

src/NHibernate.Test/Criteria/Lambda/FunctionsIntegrationFixture.cs

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,14 +113,79 @@ public void SqrtSingleOrDefault()
113113
{
114114
var sqrtOfAge = s.QueryOver<Person>()
115115
.Where(p => p.Name == "p1")
116-
.Select(p => p.Age.Sqrt())
116+
.Select(p => Math.Round(p.Age.Sqrt(), 2))
117117
.SingleOrDefault<object>();
118118

119119
sqrtOfAge.Should().Be.InstanceOf<double>();
120120
string.Format("{0:0.00}", sqrtOfAge).Should().Be((9.49).ToString());
121121
}
122122
}
123123

124+
125+
[Test]
126+
public void RoundDoubleWithOneArgument()
127+
{
128+
using (var s = OpenSession())
129+
using (s.BeginTransaction())
130+
{
131+
var roundedValue = s.QueryOver<Person>()
132+
.Where(p => p.Name == "p1")
133+
.Select(p => Math.Round(p.Age.Sqrt()))
134+
.SingleOrDefault<object>();
135+
136+
roundedValue.Should().Be.InstanceOf<double>();
137+
Assert.That(roundedValue, Is.EqualTo(9));
138+
}
139+
}
140+
141+
[Test]
142+
public void RoundDecimalWithOneArgument()
143+
{
144+
using (var s = OpenSession())
145+
using (s.BeginTransaction())
146+
{
147+
var roundedValue = s.QueryOver<Person>()
148+
.Where(p => p.Name == "p1")
149+
.Select(p => Math.Round((decimal) p.Age.Sqrt()))
150+
.SingleOrDefault<object>();
151+
152+
roundedValue.Should().Be.InstanceOf<double>();
153+
Assert.That(roundedValue, Is.EqualTo(9));
154+
}
155+
}
156+
157+
[Test]
158+
public void RoundDoubleWithTwoArguments()
159+
{
160+
using (var s = OpenSession())
161+
using (s.BeginTransaction())
162+
{
163+
var roundedValue = s.QueryOver<Person>()
164+
.Where(p => p.Name == "p1")
165+
.Select(p => Math.Round(p.Age.Sqrt() , 3))
166+
.SingleOrDefault<object>();
167+
168+
roundedValue.Should().Be.InstanceOf<double>();
169+
Assert.That(roundedValue, Is.EqualTo(9.487).Within(0.000001));
170+
}
171+
}
172+
173+
[Test]
174+
public void RoundDecimalWithTwoArguments()
175+
{
176+
using (var s = OpenSession())
177+
using (s.BeginTransaction())
178+
{
179+
var roundedValue = s.QueryOver<Person>()
180+
.Where(p => p.Name == "p1")
181+
.Select(p => Math.Round((decimal) p.Age.Sqrt(), 3))
182+
.SingleOrDefault<object>();
183+
184+
roundedValue.Should().Be.InstanceOf<double>();
185+
Assert.That(roundedValue, Is.EqualTo(9.487).Within(0.000001));
186+
}
187+
}
188+
124189
[Test]
125190
public void FunctionsToLowerToUpper()
126191
{

src/NHibernate/Criterion/ProjectionsExtensions.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,20 @@ internal static IProjection ProcessInt64Abs(MethodCallExpression methodCallExpre
245245
return Projections.SqlFunction("abs", NHibernateUtil.Int64, property);
246246
}
247247

248+
249+
internal static IProjection ProcessRound(MethodCallExpression methodCallExpression)
250+
{
251+
IProjection innerProjection =
252+
ExpressionProcessor.FindMemberProjection(methodCallExpression.Arguments[0]).AsProjection();
253+
254+
IProjection digitsProjection = Projections.Constant(0);
255+
if (methodCallExpression.Arguments.Count > 1)
256+
digitsProjection = ExpressionProcessor.FindMemberProjection(methodCallExpression.Arguments[1]).AsProjection();
257+
258+
return Projections.SqlFunction("round", NHibernateUtil.Double, innerProjection, digitsProjection);
259+
}
260+
261+
248262
/// <summary>
249263
/// Project SQL function abs()
250264
/// Note: throws an exception outside of a QueryOver expression

src/NHibernate/Impl/ExpressionProcessor.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,11 @@ static ExpressionProcessor()
200200
RegisterCustomProjection(() => ProjectionsExtensions.Abs(default(int)), ProjectionsExtensions.ProcessIntAbs);
201201
RegisterCustomProjection(() => ProjectionsExtensions.Abs(default(double)), ProjectionsExtensions.ProcessDoubleAbs);
202202
RegisterCustomProjection(() => ProjectionsExtensions.Abs(default(Int64)), ProjectionsExtensions.ProcessInt64Abs);
203+
204+
RegisterCustomProjection(() => Math.Round(default(double)), ProjectionsExtensions.ProcessRound);
205+
RegisterCustomProjection(() => Math.Round(default(decimal)), ProjectionsExtensions.ProcessRound);
206+
RegisterCustomProjection(() => Math.Round(default(double), default(int)), ProjectionsExtensions.ProcessRound);
207+
RegisterCustomProjection(() => Math.Round(default(decimal), default(int)), ProjectionsExtensions.ProcessRound);
203208
}
204209

205210
private static ICriterion Eq(ProjectionInfo property, object value)

0 commit comments

Comments
 (0)