Skip to content

Commit

Permalink
Support for BETWEEN
Browse files Browse the repository at this point in the history
  • Loading branch information
ralmsdeveloper committed Oct 4, 2018
1 parent 914357e commit 47c2b4a
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 0 deletions.
30 changes: 30 additions & 0 deletions src/EFCore.Relational/Query/Sql/DefaultQuerySqlGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1344,7 +1344,37 @@ protected override Expression VisitBinary(BinaryExpression binaryExpression)
_relationalCommandBuilder.Append(")");

break;
case ExpressionType.OrElse:
case ExpressionType.AndAlso:

This comment has been minimized.

Copy link
@ralmsdeveloper

ralmsdeveloper Oct 4, 2018

Author Owner

I tried to use the 'when' here, but it got really ugly, I did not think it was the best option, so I preferred to use 'if'.

{
if (binaryExpression.Left.RemoveConvert() is BinaryExpression leftBinary
&& binaryExpression.Right.RemoveConvert() is BinaryExpression rightBinary
&& (leftBinary.NodeType == ExpressionType.LessThan || leftBinary.NodeType == ExpressionType.GreaterThanOrEqual)
&& (rightBinary.NodeType == ExpressionType.GreaterThan || rightBinary.NodeType == ExpressionType.LessThanOrEqual)
&& leftBinary.Left.Equals(rightBinary.Left))
{
Visit(leftBinary.Left);

if(binaryExpression.NodeType == ExpressionType.OrElse)
{
_relationalCommandBuilder.Append(" NOT");
}

_relationalCommandBuilder.Append(" BETWEEN ");

Visit(leftBinary.Right);

_relationalCommandBuilder.Append(" AND ");

Visit(rightBinary.Right);

return binaryExpression;
}
else
{
goto default;
}
}
default:
var needParens = binaryExpression.Left.RemoveConvert() is BinaryExpression leftBinaryExpression
&& leftBinaryExpression.NodeType != ExpressionType.Coalesce;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore.TestModels.Northwind;
using Microsoft.EntityFrameworkCore.TestUtilities;
using Microsoft.EntityFrameworkCore.TestUtilities.Xunit;
using Xunit;
using Xunit.Abstractions;

Expand Down Expand Up @@ -4724,6 +4725,52 @@ ORDER BY [o0].[OrderID]
))");
}

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual async Task Select_where_between_cast(bool isAsync)
{
using (var ctx = CreateContext())
{
await ctx.Employees.Where(p => p.EmployeeID >= 2 && p.EmployeeID <= 10).ToListAsync();
}

AssertSql(
@"SELECT [p].[EmployeeID], [p].[City], [p].[Country], [p].[FirstName], [p].[ReportsTo], [p].[Title]
FROM [Employees] AS [p]
WHERE [p].[EmployeeID] BETWEEN CAST(2 AS bigint) AND CAST(10 AS bigint)");
}

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual async Task Select_where_between(bool isAsync)
{
using (var ctx = CreateContext())
{
await ctx.Orders.Where(p => p.OrderID >= 2 && p.OrderID <= 10).ToListAsync();
}

AssertSql(
@"SELECT [p].[OrderID], [p].[CustomerID], [p].[EmployeeID], [p].[OrderDate]
FROM [Orders] AS [p]
WHERE [p].[OrderID] BETWEEN 2 AND 10");
}

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual async Task Select_where_not_between(bool isAsync)
{
using (var ctx = CreateContext())
{
await ctx.Orders.Where(p => !(p.OrderID >= 2 && p.OrderID <= 10)).ToListAsync();
}

AssertSql(
@"SELECT [p].[OrderID], [p].[CustomerID], [p].[EmployeeID], [p].[OrderDate]
FROM [Orders] AS [p]
WHERE [p].[OrderID] NOT BETWEEN 2 AND 10");
}


private void AssertSql(params string[] expected)
=> Fixture.TestSqlLoggerFactory.AssertBaseline(expected);

Expand Down

2 comments on commit 47c2b4a

@ralmsdeveloper
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the PR can be accepted, I will implement the tests for SQLite and Oracle and Firebird.

@smitpatel
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should fit in pipeline in CompositePredicateExpressionVisitor rather than SQL gen phase.
The fix would be much more involved than this. To match large variety of variations arising.

Please sign in to comment.