Skip to content

Commit 8eb8226

Browse files
committed
CSHARP-5473: Provide API to turn LINQ expression into MQL.
1 parent cc9b265 commit 8eb8226

File tree

3 files changed

+75
-0
lines changed

3 files changed

+75
-0
lines changed

src/MongoDB.Driver/Linq/IMongoQueryProvider.cs

+9
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,15 @@ public interface IMongoQueryProvider : IQueryProvider
4040
/// <param name="cancellationToken">The cancellation token.</param>
4141
/// <returns>The value that results from executing the specified query.</returns>
4242
Task<TResult> ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken = default(CancellationToken));
43+
44+
/// <summary>
45+
/// Translates an IQueryable to MQL.
46+
/// </summary>
47+
/// <param name="queryable">The IQueryable.</param>
48+
/// <param name="outputSerializer">The output serializer.</param>
49+
/// <typeparam name="TResult">The type of the result.</typeparam>
50+
/// <returns>An array of MQL pipeline stages represented as BsonDocuments.</returns>
51+
BsonDocument[] Translate<TResult>(IQueryable<TResult> queryable, out IBsonSerializer<TResult> outputSerializer);
4352
}
4453

4554
/// <summary>

src/MongoDB.Driver/Linq/Linq3Implementation/MongoQueryProvider.cs

+10
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ protected MongoQueryProvider(
5555
public abstract TResult Execute<TResult>(Expression expression);
5656
public abstract Task<TResult> ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken);
5757
public abstract ExpressionTranslationOptions GetTranslationOptions();
58+
public abstract BsonDocument[] Translate<TResult>(IQueryable<TResult> queryable, out IBsonSerializer<TResult> outputSerializer);
5859
}
5960

6061
internal sealed class MongoQueryProvider<TDocument> : MongoQueryProvider
@@ -152,5 +153,14 @@ public override ExpressionTranslationOptions GetTranslationOptions()
152153
var database = _database ?? _collection?.Database;
153154
return translationOptions.AddMissingOptionsFrom(database?.Client.Settings.TranslationOptions);
154155
}
156+
157+
public override BsonDocument[] Translate<TResult>(IQueryable<TResult> queryable, out IBsonSerializer<TResult> outputSerializer)
158+
{
159+
var translationOptions = GetTranslationOptions();
160+
var executableQuery = ExpressionToExecutableQueryTranslator.Translate<TDocument, TResult>(provider: this, queryable.Expression, translationOptions);
161+
var stages = executableQuery.Pipeline.Ast.Stages;
162+
outputSerializer = (IBsonSerializer<TResult>)executableQuery.Pipeline.OutputSerializer;
163+
return stages.Select(s => s.Render().AsBsonDocument).ToArray();
164+
}
155165
}
156166
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/* Copyright 2010-present MongoDB Inc.
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
using System.Linq;
17+
using FluentAssertions;
18+
using MongoDB.Driver.Linq;
19+
using Xunit;
20+
21+
namespace MongoDB.Driver.Tests.Linq.Linq3Implementation.Jira
22+
{
23+
public class CSharp5473Tests : Linq3IntegrationTest
24+
{
25+
[Fact]
26+
public void Select_decimal_divide_should_work()
27+
{
28+
var collection = GetCollection();
29+
30+
var queryable = collection.AsQueryable()
31+
.Select(x => x.X + 1);
32+
33+
var provider = (IMongoQueryProvider)queryable.Provider;
34+
var stages = provider.Translate(queryable, out var outputSerializer);
35+
AssertStages(stages, "{ $project : { _v : { $add : ['$X', 1] }, _id : 0 } }");
36+
37+
var result = queryable.First();
38+
result.Should().Be(2);
39+
}
40+
41+
private IMongoCollection<C> GetCollection()
42+
{
43+
var collection = GetCollection<C>("test");
44+
CreateCollection(
45+
collection,
46+
new C { Id = 1, X = 1 });
47+
return collection;
48+
}
49+
50+
private class C
51+
{
52+
public int Id { get; set; }
53+
public int X { get; set; }
54+
}
55+
}
56+
}

0 commit comments

Comments
 (0)