Skip to content

Commit 5a9515e

Browse files
committed
Cosmos: Add translator for Regex.IsMatch method
Fixes dotnet#28078
1 parent 5da4122 commit 5a9515e

File tree

3 files changed

+78
-7
lines changed

3 files changed

+78
-7
lines changed

src/EFCore.Cosmos/Query/Internal/CosmosMethodCallTranslatorProvider.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ public CosmosMethodCallTranslatorProvider(
3333
new CosmosStringMethodTranslator(sqlExpressionFactory),
3434
new ContainsTranslator(sqlExpressionFactory),
3535
new RandomTranslator(sqlExpressionFactory),
36-
new MathTranslator(sqlExpressionFactory)
36+
new MathTranslator(sqlExpressionFactory),
37+
new RegexMethodTranslator(sqlExpressionFactory)
3738
//new LikeTranslator(sqlExpressionFactory),
3839
//new EnumHasFlagTranslator(sqlExpressionFactory),
3940
//new GetValueOrDefaultTranslator(sqlExpressionFactory),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Text.RegularExpressions;
5+
6+
namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal;
7+
8+
/// <summary>
9+
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
10+
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
11+
/// any release. You should only use it directly in your code with extreme caution and knowing that
12+
/// doing so can result in application failures when updating to a new Entity Framework Core release.
13+
/// </summary>
14+
public class RegexMethodTranslator : IMethodCallTranslator
15+
{
16+
private static readonly HashSet<MethodInfo> MethodInfoDataLengthMapping
17+
= new()
18+
{
19+
typeof(Regex).GetRuntimeMethod(nameof(Regex.IsMatch), new[] { typeof(string), typeof(string) })!,
20+
typeof(Regex).GetRuntimeMethod(nameof(Regex.IsMatch), new[] { typeof(ReadOnlySpan<char>), typeof(string) })!
21+
};
22+
23+
private readonly ISqlExpressionFactory _sqlExpressionFactory;
24+
25+
/// <summary>
26+
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
27+
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
28+
/// any release. You should only use it directly in your code with extreme caution and knowing that
29+
/// doing so can result in application failures when updating to a new Entity Framework Core release.
30+
/// </summary>
31+
public RegexMethodTranslator(ISqlExpressionFactory sqlExpressionFactory)
32+
{
33+
_sqlExpressionFactory = sqlExpressionFactory;
34+
}
35+
36+
/// <summary>
37+
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
38+
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
39+
/// any release. You should only use it directly in your code with extreme caution and knowing that
40+
/// doing so can result in application failures when updating to a new Entity Framework Core release.
41+
/// </summary>
42+
public virtual SqlExpression? Translate(
43+
SqlExpression? instance,
44+
MethodInfo method,
45+
IReadOnlyList<SqlExpression> arguments,
46+
IDiagnosticsLogger<DbLoggerCategory.Query> logger)
47+
{
48+
if (MethodInfoDataLengthMapping.Contains(method))
49+
{
50+
var typeMapping = arguments.Count == 2
51+
? ExpressionExtensions.InferTypeMapping(arguments[0], arguments[1])
52+
: ExpressionExtensions.InferTypeMapping(arguments[0], arguments[1], arguments[2]);
53+
54+
var newArguments = arguments.Select(e => _sqlExpressionFactory.ApplyTypeMapping(e, typeMapping));
55+
56+
return _sqlExpressionFactory.Function(
57+
"RegexMatch",
58+
newArguments,
59+
method.ReturnType,
60+
typeMapping);
61+
}
62+
63+
return null;
64+
}
65+
}
66+

test/EFCore.Cosmos.FunctionalTests/Query/NorthwindFunctionsQueryCosmosTest.cs

+10-6
Original file line numberDiff line numberDiff line change
@@ -1204,18 +1204,22 @@ public override async Task Int_Compare_to_simple_zero(bool async)
12041204

12051205
public override async Task Regex_IsMatch_MethodCall(bool async)
12061206
{
1207-
// Cosmos client evaluation. Issue #17246.
1208-
await AssertTranslationFailed(() => base.Regex_IsMatch_MethodCall(async));
1207+
await base.Regex_IsMatch_MethodCall(async);
12091208

1210-
AssertSql();
1209+
AssertSql(
1210+
@"SELECT c
1211+
FROM root c
1212+
WHERE ((c[""Discriminator""] = ""Customer"") AND RegexMatch(c[""CustomerID""], ""^T""))");
12111213
}
12121214

12131215
public override async Task Regex_IsMatch_MethodCall_constant_input(bool async)
12141216
{
1215-
// Cosmos client evaluation. Issue #17246.
1216-
await AssertTranslationFailed(() => base.Regex_IsMatch_MethodCall_constant_input(async));
1217+
await base.Regex_IsMatch_MethodCall_constant_input(async);
12171218

1218-
AssertSql();
1219+
AssertSql(
1220+
@"SELECT c
1221+
FROM root c
1222+
WHERE ((c[""Discriminator""] = ""Customer"") AND RegexMatch(""ALFKI"", c[""CustomerID""]))");
12191223
}
12201224

12211225
[ConditionalTheory]

0 commit comments

Comments
 (0)