Skip to content

Commit

Permalink
CSHARP-4140: Only use $getField when absolutely necessary.
Browse files Browse the repository at this point in the history
  • Loading branch information
rstam authored and BorisDog committed May 3, 2022
1 parent d2a5f59 commit cd18d88
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -67,17 +67,14 @@ public bool HasSafeFieldName(out string fieldName)
constantFieldName.Value is BsonString stringfieldName)
{
fieldName = stringfieldName.Value;
if (fieldName.Length > 0 && IsSafeFirstChar(fieldName[0]) && fieldName.Skip(1).All(c => IsSafeSubsequentChar(c)))
if (fieldName.Length > 0 && fieldName[0] != '$' && !fieldName.Contains('.'))
{
return true;
}
}

fieldName = null;
return false;

static bool IsSafeFirstChar(char c) => c == '_' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
static bool IsSafeSubsequentChar(char c) => IsSafeFirstChar(c) || (c >= '0' && c <= '9');
}

public override BsonValue Render()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/* Copyright 2010-present MongoDB Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

using System.Linq;
using FluentAssertions;
using MongoDB.Bson;
using Xunit;

namespace MongoDB.Driver.Tests.Linq.Linq3ImplementationTests.Jira
{
public class CSharp4140Tests : Linq3IntegrationTest
{
[Theory]
[InlineData("abc")]
[InlineData("123")]
[InlineData("12$")]
[InlineData("!@#")]
public void Should_not_use_getField(string fieldName)
{
var collection = GetCollection<BsonDocument>();
CreateCollection(collection, new BsonDocument(fieldName, 123));
var queryable = collection.AsQueryable()
.Select(x => x[fieldName]);

var stages = Translate(collection, queryable);
AssertStages(stages, $"{{ $project : {{ _v : '${fieldName}', _id : 0 }} }}");

var results = queryable.ToList();
results.Should().Equal(123);
}

[Theory]
[InlineData("")]
[InlineData(".")]
[InlineData(".a")]
[InlineData("a.")]
public void Should_use_getField(string fieldName)
{
var collection = GetCollection<BsonDocument>();
CreateCollection(collection, new BsonDocument(fieldName, 123));
var queryable = collection.AsQueryable()
.Select(x => x[fieldName]);

var stages = Translate(collection, queryable);
AssertStages(stages, $"{{ $project : {{ _v : {{ $getField : {{ field : '{fieldName}', input : '$$ROOT' }} }}, _id : 0 }} }}");

var results = queryable.ToList();
results.Should().Equal(123);
}

[Theory]
[InlineData("$")]
[InlineData("$a")]
[InlineData("$$a")]
[InlineData("$a$")]
public void Should_use_getField_with_literal(string fieldName)
{
var collection = GetCollection<BsonDocument>();
CreateCollection(collection, new BsonDocument(fieldName, 123));
var queryable = collection.AsQueryable()
.Select(x => x[fieldName]);

var stages = Translate(collection, queryable);
AssertStages(stages, $"{{ $project : {{ _v : {{ $getField : {{ field : {{ $literal : '{fieldName}' }}, input : '$$ROOT' }} }}, _id : 0 }} }}");

var results = queryable.ToList();
results.Should().Equal(123);
}
}
}

0 comments on commit cd18d88

Please sign in to comment.