Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit c2ed99b

Browse files
committed
Merge remote-tracking branch 'refs/remotes/ServiceStack/master'
2 parents 4412ab3 + 3b120bb commit c2ed99b

File tree

4 files changed

+190
-2
lines changed

4 files changed

+190
-2
lines changed

src/ServiceStack.OrmLite/Expressions/SqlExpression.cs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,7 +1298,7 @@ protected virtual object VisitBinary(BinaryExpression b)
12981298

12991299
if (!(left is PartialSqlString) && !(right is PartialSqlString))
13001300
{
1301-
var result = CachedExpressionCompiler.Evaluate(b);
1301+
var result = CachedExpressionCompiler.Evaluate(PreEvaluateBinary(b, left, right));
13021302
return result;
13031303
}
13041304

@@ -1363,7 +1363,7 @@ protected virtual object VisitBinary(BinaryExpression b)
13631363
}
13641364
else if (!(left is PartialSqlString) && !(right is PartialSqlString))
13651365
{
1366-
var evaluatedValue = CachedExpressionCompiler.Evaluate(b);
1366+
var evaluatedValue = CachedExpressionCompiler.Evaluate(PreEvaluateBinary(b, left, right));
13671367
var result = VisitConstant(Expression.Constant(evaluatedValue));
13681368
return result;
13691369
}
@@ -1402,6 +1402,23 @@ protected virtual object VisitBinary(BinaryExpression b)
14021402
}
14031403
}
14041404

1405+
private BinaryExpression PreEvaluateBinary(BinaryExpression b, object left, object right)
1406+
{
1407+
var visitedBinaryExp = b;
1408+
1409+
if (IsParameterAccess(b.Left) || IsParameterAccess(b.Right))
1410+
{
1411+
var eLeft = !IsParameterAccess(b.Left) ? b.Left : Expression.Constant(left, b.Left.Type);
1412+
var eRight = !IsParameterAccess(b.Right) ? b.Right : Expression.Constant(right, b.Right.Type);
1413+
if (b.NodeType == ExpressionType.Coalesce)
1414+
visitedBinaryExp = Expression.Coalesce(eLeft, eRight, b.Conversion);
1415+
else
1416+
visitedBinaryExp = Expression.MakeBinary(b.NodeType, eLeft, eRight, b.IsLiftedToNull, b.Method);
1417+
}
1418+
1419+
return visitedBinaryExp;
1420+
}
1421+
14051422
/// <summary>
14061423
/// Determines whether the expression is the parameter inside MemberExpression which should be compared with TrueExpression.
14071424
/// </summary>
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
using System;
2+
using System.Data;
3+
using System.Linq.Expressions;
4+
using NUnit.Framework;
5+
using ServiceStack.OrmLite.Sqlite;
6+
7+
8+
namespace ServiceStack.OrmLite.Tests
9+
{
10+
public class Waybill
11+
{
12+
public int Id { get; set; }
13+
14+
public int Number { get; set; }
15+
16+
public string Name { get; set; }
17+
18+
public string VirtProperty => "WaybillVirtPropertyValue";
19+
20+
public string VirtProperty2 => "WaybillVirtPropertyValue2";
21+
}
22+
23+
public class CustomSqlServerDialectProvider : SqliteOrmLiteDialectProvider
24+
{
25+
public override SqlExpression<T> SqlExpression<T>()
26+
{
27+
return new CustomSqlExpression<T>(this);
28+
}
29+
}
30+
31+
public class CustomSqlExpression<T> : SqlExpression<T>
32+
{
33+
34+
public CustomSqlExpression(IOrmLiteDialectProvider dialectProvider) : base(dialectProvider)
35+
{
36+
}
37+
38+
protected override Object GetMemberExpression(MemberExpression m)
39+
{
40+
if (m.Member.DeclaringType == typeof(Waybill))
41+
{
42+
if (m.Member.Name == nameof(Waybill.VirtProperty))
43+
return "WaybillVirtPropertyValue";
44+
if (m.Member.Name == nameof(Waybill.VirtProperty2))
45+
return "WaybillVirtPropertyValue2";
46+
}
47+
48+
return base.GetMemberExpression(m);
49+
}
50+
}
51+
52+
[TestFixture]
53+
public class CustomSqlExpressionTests : OrmLiteTestBase
54+
{
55+
private IDbConnection Db;
56+
57+
[OneTimeSetUp]
58+
public void CustomInit()
59+
{
60+
ConnectionString = Config.SqliteMemoryDb;
61+
DbFactory = new OrmLiteConnectionFactory(ConnectionString, new CustomSqlServerDialectProvider());
62+
}
63+
64+
[SetUp]
65+
public void Setup()
66+
{
67+
using (var db = OpenDbConnection())
68+
{
69+
db.DropTable<Waybill>();
70+
71+
db.CreateTable<Waybill>();
72+
db.Insert(new Waybill {Id = 1, Number = 100, Name = "first"});
73+
db.Insert(new Waybill {Id = 2, Number = 200, Name = "second"});
74+
db.Insert(new Waybill {Id = 3, Number = 300, Name = "third"});
75+
}
76+
Db = OpenDbConnection();
77+
}
78+
79+
[TearDown]
80+
public void TearDown()
81+
{
82+
Db.Dispose();
83+
}
84+
85+
[Test]
86+
public void Can_Where_using_constant_filter1()
87+
{
88+
System.Linq.Expressions.Expression<Func<Waybill, bool>> filter = x => x.VirtProperty == "WaybillVirtPropertyValue";
89+
var q = Db.From<Waybill>().Where(filter);
90+
var target = Db.Select(q);
91+
Assert.AreEqual(3, target.Count);
92+
}
93+
94+
[Test]
95+
public void Can_Where_using_constant_filter2()
96+
{
97+
System.Linq.Expressions.Expression<Func<Waybill, bool>> filter = x => x.VirtProperty == "Any";
98+
var q = Db.From<Waybill>().Where(filter);
99+
var target = Db.Select(q);
100+
Assert.AreEqual(0, target.Count);
101+
}
102+
103+
[Test]
104+
public void Can_Where_using_constant_filter3()
105+
{
106+
System.Linq.Expressions.Expression<Func<Waybill, bool>> filter = x => x.VirtProperty != "WaybillVirtPropertyValue";
107+
var q = Db.From<Waybill>().Where(filter);
108+
var target = Db.Select(q);
109+
Assert.AreEqual(0, target.Count);
110+
}
111+
112+
[Test]
113+
public void Can_Where_using_constant_filter4()
114+
{
115+
System.Linq.Expressions.Expression<Func<Waybill, bool>> filter = x => x.VirtProperty != "Any";
116+
var q = Db.From<Waybill>().Where(filter);
117+
var target = Db.Select(q);
118+
Assert.AreEqual(3, target.Count);
119+
}
120+
121+
[Test]
122+
public void Can_Where_using_constant_filter5()
123+
{
124+
System.Linq.Expressions.Expression<Func<Waybill, bool>> filter = x => x.VirtProperty == "WaybillVirtPropertyValue" || x.VirtProperty2 == "WaybillVirtPropertyValue2";
125+
var q = Db.From<Waybill>().Where(filter);
126+
var target = Db.Select(q);
127+
Assert.AreEqual(3, target.Count);
128+
}
129+
130+
[Test]
131+
public void Can_Where_using_constant_filter6()
132+
{
133+
System.Linq.Expressions.Expression<Func<Waybill, bool>> filter = x => x.VirtProperty == "WaybillVirtPropertyValue" && x.VirtProperty2 == "WaybillVirtPropertyValue2";
134+
var q = Db.From<Waybill>().Where(filter);
135+
var target = Db.Select(q);
136+
Assert.AreEqual(3, target.Count);
137+
}
138+
139+
[Test]
140+
public void Can_Where_using_constant_filter7()
141+
{
142+
System.Linq.Expressions.Expression<Func<Waybill, bool>> filter = x => x.VirtProperty == "WaybillVirtPropertyValue" || x.VirtProperty2 == "Any";
143+
var q = Db.From<Waybill>().Where(filter);
144+
var target = Db.Select(q);
145+
Assert.AreEqual(3, target.Count);
146+
}
147+
148+
[Test]
149+
public void Can_Where_using_constant_filter8()
150+
{
151+
System.Linq.Expressions.Expression<Func<Waybill, bool>> filter = x => x.VirtProperty == "WaybillVirtPropertyValue" && x.VirtProperty2 == "Any";
152+
var q = Db.From<Waybill>().Where(filter);
153+
var target = Db.Select(q);
154+
Assert.AreEqual(0, target.Count);
155+
}
156+
}
157+
}

tests/ServiceStack.OrmLite.Tests/ExpressionVisitorTests.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,19 @@ public void Can_Where_using_filter_with_Concat()
489489
Assert.That(target.Count, Is.EqualTo(1));
490490
}
491491

492+
[Test]
493+
public void Can_Where_using_constant_filter()
494+
{
495+
object left = null;
496+
var right = new PartialSqlString("null");
497+
498+
System.Linq.Expressions.Expression<Func<TestType, bool>> filter = x => left == right;
499+
var q = Db.From<TestType>().Where(filter);//todo: here Where: null is NULL. May be need to change to 1=1 ?
500+
var target = Db.Select(q);
501+
Assert.That(target.Count, Is.EqualTo(4));
502+
503+
}
504+
492505
private int MethodReturningInt(int val)
493506
{
494507
return val;

tests/ServiceStack.OrmLite.Tests/ServiceStack.OrmLite.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@
136136
<Compile Include="Async\SqlExpressionTests.cs" />
137137
<Compile Include="Async\SqlServerProviderTestsAsync.cs" />
138138
<Compile Include="Async\UpdateAsyncTests.cs" />
139+
<Compile Include="CustomSqlExpressionTests.cs" />
139140
<Compile Include="Expression\JoinAliasTests.cs" />
140141
<Compile Include="Expression\RestrictionTests.cs" />
141142
<Compile Include="Expression\SqlExpressionDeleteTests.cs" />

0 commit comments

Comments
 (0)