Skip to content

Commit

Permalink
Flatten nested queries generated by OData $skip and $select combinati…
Browse files Browse the repository at this point in the history
…ons.
  • Loading branch information
chriseldredge committed Sep 9, 2014
1 parent e7126dc commit 2aaa2c2
Show file tree
Hide file tree
Showing 8 changed files with 167 additions and 6 deletions.
2 changes: 1 addition & 1 deletion Ciao.props
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Bootstrap" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Version">
<VersionPrefix>3.3.3</VersionPrefix>
<VersionPrefix>3.3.4</VersionPrefix>
<VersionSuffix></VersionSuffix>
</PropertyGroup>

Expand Down
5 changes: 2 additions & 3 deletions source/Lucene.Net.Linq.Tests/Integration/SelectTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Linq;
using System.Linq;
using Lucene.Net.Analysis;
using Lucene.Net.Linq.Analysis;
using Lucene.Net.Linq.Mapping;
Expand Down Expand Up @@ -517,4 +516,4 @@ public void Where_AnyField_StartsWith()

}

}
}
114 changes: 114 additions & 0 deletions source/Lucene.Net.Linq.Tests/Integration/SubQueryTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
using System.Linq;
using NUnit.Framework;

namespace Lucene.Net.Linq.Tests.Integration
{
[TestFixture]
public class SubQueryTests : IntegrationTestBase
{
[SetUp]
public void SetUp()
{
AddDocument(new SampleDocument { Id = "a", Scalar = 5});
AddDocument(new SampleDocument { Id = "b", Scalar = 1});
AddDocument(new SampleDocument { Id = "c", Scalar = 3});
}

[Test]
public void SubquerySkip()
{
var docs = provider.AsQueryable<SampleDocument>();

var results = (from outer in
(from d in docs
orderby d.Id
select d).Skip(2)
select new { outer.Id })
.ToList();

Assert.That(results.Select(d => d.Id).ToArray(), Is.EqualTo(new[] { "c" }));
}

[Test]
public void MainSkipSubquerySkip()
{
var docs = provider.AsQueryable<SampleDocument>();

var results = (from outer in
(from d in docs
orderby d.Id descending
select d).Skip(1)
select new { outer.Id })
.Skip(1)
.ToList();

Assert.That(results.Select(d => d.Id).ToArray(), Is.EqualTo(new[] { "a" }));
}

[Test]
public void MainOrderBy()
{
var docs = provider.AsQueryable<SampleDocument>();

var results = (from outer in
(from d in docs select d)
orderby outer.Id descending
select new { outer.Id })
.ToList();

Assert.That(results.Select(d => d.Id).ToArray(), Is.EqualTo(new[] { "c", "b", "a" }));
}

[Test]
public void SubQueryOrderWinsOnConflictingOrder()
{
var docs = provider.AsQueryable<SampleDocument>();

var results = (from outer in
(from d in docs
orderby d.Scalar
select d).Skip(1)
orderby outer.Id
select new { outer.Id })
.Skip(1)
.ToList();

Assert.That(results.Select(d => d.Id).ToArray(), Is.EqualTo(new[] { "a" }));
}

[Test]
public void AllowsConflictingOrderOnNoSkipTake()
{
var docs = provider.AsQueryable<SampleDocument>();

var results = (from outer in
(from d in docs
orderby d.Scalar
select d)
orderby outer.Id
select new { outer.Id })
.ToList();

Assert.That(results.Select(d => d.Id).ToArray(), Is.EqualTo(new[] { "b", "c", "a" }));
}

[Test]
public void AllowsSameOrderOnSubSkipTake()
{
var docs = provider.AsQueryable<SampleDocument>();

var results = (from outer in
(from d in docs
orderby d.Scalar
orderby d.Id
select d).Skip(1)
orderby outer.Scalar
orderby outer.Id
select new { outer.Id })
.ToList();

Assert.That(results.Select(d => d.Id).ToArray(), Is.EqualTo(new[] { "c", "a" }));
}

}
}
1 change: 1 addition & 0 deletions source/Lucene.Net.Linq.Tests/Lucene.Net.Linq.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@
<Compile Include="Integration\RangeTests.cs" />
<Compile Include="Integration\ReleaseTests.cs" />
<Compile Include="Integration\StatisticTests.cs" />
<Compile Include="Integration\SubQueryTests.cs" />
<Compile Include="LuceneQueryExecutorTests.cs" />
<Compile Include="Mapping\FieldMappingInfoBuilderSortFieldTests.cs" />
<Compile Include="Mapping\ReflectionDocumentBoostMapperTests.cs" />
Expand Down
1 change: 1 addition & 0 deletions source/Lucene.Net.Linq/Lucene.Net.Linq.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@
<Compile Include="Search\Function\DelegatingCustomScoreQuery.cs" />
<Compile Include="Transformation\TreeVisitors\AllowSpecialCharactersMethodExpressionTreeVisitor.cs" />
<Compile Include="Transformation\TreeVisitors\BooleanBinaryToQueryPredicateExpressionTreeVisitor.cs" />
<Compile Include="Transformation\TreeVisitors\AggressiveSubQueryFromClauseFlattener.cs" />
<Compile Include="Transformation\TreeVisitors\FuzzyMethodCallTreeVisitor.cs" />
<Compile Include="Transformation\TreeVisitors\BoostMethodCallTreeVisitor.cs" />
<Compile Include="Transformation\TreeVisitors\ExternallyProvidedQueryExpressionTreeVisitor.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,14 @@ public static void TransformQueryModel(QueryModel queryModel)
var instance = new QueryModelTransformer();

queryModel.Accept(instance);
}

public override void VisitMainFromClause(MainFromClause fromClause, QueryModel queryModel)
{
Log.Trace(m => m("Original QueryModel: {0}", queryModel));
new AggressiveSubQueryFromClauseFlattener().VisitMainFromClause(fromClause, queryModel);
Log.Trace(m => m("Transformed QueryModel after AggressiveSubQueryFromClauseFlattener: {0}", queryModel));
base.VisitMainFromClause(fromClause, queryModel);
}

public override void VisitWhereClause(WhereClause whereClause, QueryModel queryModel, int index)
Expand Down Expand Up @@ -118,4 +125,4 @@ private void ExpandCompositeOrderings(OrderByClause orderByClause)
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System;
using System.Linq;
using Remotion.Linq;
using Remotion.Linq.Clauses;
using Remotion.Linq.Clauses.Expressions;
using Remotion.Linq.Clauses.ResultOperators;
using Remotion.Linq.Transformations;

namespace Lucene.Net.Linq.Transformation.TreeVisitors
{
internal class AggressiveSubQueryFromClauseFlattener : SubQueryFromClauseFlattener
{
protected override void CheckFlattenable(QueryModel subQueryModel)
{
var first = subQueryModel.ResultOperators.FirstOrDefault();
if (first != null)
{
throw new NotSupportedException(first.GetType() + " is not supported in sub-queries. Sub-queries may only use SequenceTypePreservingResultOperatorBase subclasses.");
}
}

protected override void FlattenSubQuery(SubQueryExpression subQueryExpression, FromClauseBase fromClause, QueryModel queryModel,
int destinationIndex)
{
var subQueryModel = subQueryExpression.QueryModel;
MoveResultOperatorsToParent(queryModel, subQueryModel);
base.FlattenSubQuery(subQueryExpression, fromClause, queryModel, destinationIndex);
}

protected virtual void MoveResultOperatorsToParent(QueryModel queryModel, QueryModel subQueryModel)
{
foreach (var resultOperator in subQueryModel.ResultOperators.OfType<SequenceTypePreservingResultOperatorBase>().Reverse().ToList())
{
queryModel.ResultOperators.Insert(0, resultOperator);
subQueryModel.ResultOperators.Remove(resultOperator);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,4 @@ private Expression VisitQueryPredicateExpression(LuceneQueryPredicateExpression
return result;
}
}
}
}

0 comments on commit 2aaa2c2

Please sign in to comment.