Skip to content

Commit 318ee30

Browse files
matteobortolazzo#183 - Fix .In within .Any
1 parent b669800 commit 318ee30

File tree

4 files changed

+35
-12
lines changed

4 files changed

+35
-12
lines changed

src/CouchDB.Driver/Query/QueryCompiler.cs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ internal class QueryCompiler : IQueryCompiler
1717
private readonly IQueryTranslator _queryTranslator;
1818
private readonly IQuerySender _requestSender;
1919
private readonly string? _discriminator;
20+
2021
private static readonly MethodInfo RequestSendMethod
2122
= typeof(IQuerySender).GetRuntimeMethods()
2223
.Single(m => (m.Name == nameof(IQuerySender.Send)) && m.IsGenericMethod);
@@ -29,7 +30,8 @@ private static readonly MethodInfo PostProcessResultAsyncMethod
2930
= typeof(QueryCompiler).GetMethod(nameof(PostProcessResultAsync),
3031
BindingFlags.NonPublic | BindingFlags.Static);
3132

32-
public QueryCompiler(IQueryOptimizer queryOptimizer, IQueryTranslator queryTranslator, IQuerySender requestSender, string? discriminator)
33+
public QueryCompiler(IQueryOptimizer queryOptimizer, IQueryTranslator queryTranslator,
34+
IQuerySender requestSender, string? discriminator)
3335
{
3436
_queryOptimizer = queryOptimizer;
3537
_queryTranslator = queryTranslator;
@@ -57,7 +59,8 @@ private TResult SendRequest<TResult>(Expression query, bool async, CancellationT
5759
{
5860
ConstantExpression _ => SendRequestWithoutFilter<TResult>(query,
5961
async, cancellationToken),
60-
MethodCallExpression methodCallExpression => SendRequestWithFilter<TResult>(methodCallExpression, query,
62+
MethodCallExpression methodCallExpression => SendRequestWithFilter<TResult>(methodCallExpression,
63+
query,
6164
async, cancellationToken),
6265
_ => throw new ArgumentException($"Expression of type {query.GetType().Name} is not valid.")
6366
};
@@ -69,7 +72,8 @@ private TResult SendRequest<TResult>(Expression query, bool async, CancellationT
6972
}
7073
}
7174

72-
private TResult SendRequestWithoutFilter<TResult>(Expression query, bool async, CancellationToken cancellationToken)
75+
private TResult SendRequestWithoutFilter<TResult>(Expression query, bool async,
76+
CancellationToken cancellationToken)
7377
{
7478
Expression optimizedQuery = _queryOptimizer.Optimize(query, _discriminator);
7579
var body = _queryTranslator.Translate(optimizedQuery);
@@ -87,7 +91,7 @@ private TResult SendRequestWithFilter<TResult>(MethodCallExpression methodCallEx
8791
}
8892

8993
var body = _queryTranslator.Translate(optimizedQuery);
90-
94+
9195
// If no operation must be done on the list return
9296
if (!methodCallExpression.Method.IsSupportedByComposition())
9397
{
@@ -101,12 +105,12 @@ private TResult SendRequestWithFilter<TResult>(MethodCallExpression methodCallEx
101105
// Query database
102106
object couchQueryable = RequestSendMethod
103107
.MakeGenericMethod(couchListType)
104-
.Invoke(_requestSender, new object[]{ body, async, cancellationToken });
108+
.Invoke(_requestSender, new object[] { body, async, cancellationToken });
105109

106110
// Apply in-memory operations
107111
MethodInfo postProcessResultMethodInfo = (async
108-
? PostProcessResultAsyncMethod
109-
: PostProcessResultMethod)
112+
? PostProcessResultAsyncMethod
113+
: PostProcessResultMethod)
110114
.MakeGenericMethod(documentType, returnType);
111115

112116
return (TResult)postProcessResultMethodInfo.Invoke(null,
@@ -174,7 +178,7 @@ private static TResult PostProcessResult<TSource, TResult>(
174178
// Execute
175179
try
176180
{
177-
return (TResult)enumerableMethodInfo.Invoke(null, new[] {result});
181+
return (TResult)enumerableMethodInfo.Invoke(null, new[] { result });
178182
}
179183
catch (TargetInvocationException ex)
180184
{
@@ -197,4 +201,4 @@ private static async Task<TResult> PostProcessResultAsync<TSource, TResult>(
197201
return PostProcessResult<TSource, TResult>(couchList, originalMethodCall, optimizedMethodCall);
198202
}
199203
}
200-
}
204+
}

src/CouchDB.Driver/Query/QueryTranslator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,4 @@ protected override Expression VisitLambda<T>(Expression<T> l)
5555
return l;
5656
}
5757
}
58-
}
58+
}

src/CouchDB.Driver/Query/Translators/MethodCallExpressionTranslator.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -456,10 +456,21 @@ private Expression VisitInMethod(MethodCallExpression m, bool not = false)
456456
{
457457
_sb.Append('{');
458458
Visit(m.Arguments[0]);
459-
_sb.Append(not ? ":{\"$nin\":" : ":{\"$in\":");
459+
460+
var bracketOpened = _sb[^1] == '{';
461+
if (!bracketOpened)
462+
{
463+
_sb.Append(":{");
464+
}
465+
466+
_sb.Append(not ? "\"$nin\":" : "\"$in\":");
460467

461468
Visit(m.Arguments[1]);
462-
_sb.Append("}}");
469+
if (!bracketOpened)
470+
{
471+
_sb.Append("}");
472+
}
473+
_sb.Append("}");
463474
return m;
464475
}
465476

tests/CouchDB.Driver.UnitTests/Find/Find_Selector_Combinations.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,14 @@ public void ElemMatchNestedImplicitBool()
126126
@"{""selector"":{""battles"":{""$elemMatch"":{""vehicles"":{""$elemMatch"":{""canFly"":true}}}}}}",
127127
json);
128128
}
129+
130+
[Fact]
131+
public void ElemMatch_In()
132+
{
133+
var search = new[] { "battle" };
134+
var json = _rebels.Where(r => r.Skills.Any(s => s.In(search))).ToString();
135+
Assert.Equal(@"{""selector"":{""skills"":{""$elemMatch"":{""$in"":[""battle""]}}}}", json);
136+
}
129137

130138
[Fact]
131139
public void AllMatch()

0 commit comments

Comments
 (0)