Skip to content

Commit

Permalink
Fixup to Cosmos regex translation (#28261)
Browse files Browse the repository at this point in the history
Closes #28139
  • Loading branch information
roji authored Jun 17, 2022
1 parent e62e767 commit f755ffc
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 29 deletions.
39 changes: 19 additions & 20 deletions src/EFCore.Cosmos/Query/Internal/CosmosRegexTranslator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ public class CosmosRegexTranslator : IMethodCallTranslator
private static readonly MethodInfo IsMatchWithRegexOptions =
typeof(Regex).GetRuntimeMethod(nameof(Regex.IsMatch), new[] { typeof(string), typeof(string), typeof(RegexOptions) })!;

private const RegexOptions SupportedOptions = RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace;

private readonly ISqlExpressionFactory _sqlExpressionFactory;

/// <summary>
Expand Down Expand Up @@ -53,48 +51,49 @@ public CosmosRegexTranslator(ISqlExpressionFactory sqlExpressionFactory)

var (input, pattern) = (arguments[0], arguments[1]);
var typeMapping = ExpressionExtensions.InferTypeMapping(input, pattern);
(input, pattern) = (
_sqlExpressionFactory.ApplyTypeMapping(input, typeMapping),
_sqlExpressionFactory.ApplyTypeMapping(pattern, typeMapping));

if (method == IsMatch)
if (method == IsMatch || arguments[2] is SqlConstantExpression { Value: RegexOptions.None })
{
return _sqlExpressionFactory.Function(
"RegexMatch",
new[] {
_sqlExpressionFactory.ApplyTypeMapping(input, typeMapping),
_sqlExpressionFactory.ApplyTypeMapping(pattern, typeMapping)
},
typeof(bool));
return _sqlExpressionFactory.Function("RegexMatch", new[] { input, pattern }, typeof(bool));
}
else if (arguments[2] is SqlConstantExpression { Value: RegexOptions regexOptions })

if (arguments[2] is SqlConstantExpression { Value: RegexOptions regexOptions })
{
string modifier = "";
var modifier = "";

if (regexOptions.HasFlag(RegexOptions.Multiline))
{
regexOptions &= ~RegexOptions.Multiline;
modifier += "m";
}

if (regexOptions.HasFlag(RegexOptions.Singleline))
{
regexOptions &= ~RegexOptions.Singleline;
modifier += "s";
}

if (regexOptions.HasFlag(RegexOptions.IgnoreCase))
{
regexOptions &= ~RegexOptions.IgnoreCase;
modifier += "i";
}

if (regexOptions.HasFlag(RegexOptions.IgnorePatternWhitespace))
{
regexOptions &= ~RegexOptions.IgnorePatternWhitespace;
modifier += "x";
}

return (regexOptions & ~SupportedOptions) == 0
return regexOptions == 0
? _sqlExpressionFactory.Function(
"RegexMatch",
new[]
{
_sqlExpressionFactory.ApplyTypeMapping(input, typeMapping),
_sqlExpressionFactory.ApplyTypeMapping(pattern, typeMapping),
_sqlExpressionFactory.Constant(modifier)
},
new[] { input, pattern, _sqlExpressionFactory.Constant(modifier) },
typeof(bool))
: null;
: null; // TODO: Report unsupported RegexOption, #26410
}

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1235,7 +1235,7 @@ await AssertQuery(
AssertSql(
@"SELECT c
FROM root c
WHERE ((c[""Discriminator""] = ""Customer"") AND RegexMatch(c[""CustomerID""], ""^T"", """"))");
WHERE ((c[""Discriminator""] = ""Customer"") AND RegexMatch(c[""CustomerID""], ""^T""))");
}

[ConditionalTheory]
Expand Down Expand Up @@ -1313,15 +1313,19 @@ FROM root c
WHERE ((c[""Discriminator""] = ""Customer"") AND RegexMatch(c[""CustomerID""], ""^T"", ""ix""))");
}

[Fact]
public virtual void Regex_IsMatch_MethodCall_With_Unsupported_Option()
=> Assert.Throws<InvalidOperationException>(() =>
Fixture.CreateContext().Customers.Where(o => Regex.IsMatch(o.CustomerID, "^T", RegexOptions.RightToLeft)).ToList());
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Regex_IsMatch_MethodCall_With_Unsupported_Option(bool async)
=> AssertTranslationFailed(() => AssertQuery(
async,
ss => ss.Set<Customer>().Where(o => Regex.IsMatch(o.CustomerID, "^T", RegexOptions.RightToLeft))));

[Fact]
public virtual void Regex_IsMatch_MethodCall_With_Any_Unsupported_Option()
=> Assert.Throws<InvalidOperationException>(() =>
Fixture.CreateContext().Customers.Where(o => Regex.IsMatch(o.CustomerID, "^T", RegexOptions.IgnoreCase | RegexOptions.RightToLeft)).ToList());
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Regex_IsMatch_MethodCall_With_Any_Unsupported_Option(bool async)
=> AssertTranslationFailed(() => AssertQuery(
async,
ss => ss.Set<Customer>().Where(o => Regex.IsMatch(o.CustomerID, "^T", RegexOptions.IgnoreCase | RegexOptions.RightToLeft))));

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
Expand Down

0 comments on commit f755ffc

Please sign in to comment.