Query: Adds LINQ RegexMatch Extension method (#4078)

* Add support for translation to REgexmatch

* Add test and fix some indexing issues

* remove visit explicit, add some comment. Update public contract and added the baseline for the test

* add the missing baseline

* added test

* address code review

* update csproj

---------

Co-authored-by: Minh Le <leminh@microsoft.com>
This commit is contained in:
leminh98 2023-10-03 15:37:11 -07:00 коммит произвёл GitHub
Родитель 101b9b1ad5
Коммит 11fa17b6e9
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
9 изменённых файлов: 359 добавлений и 75 удалений

Просмотреть файл

@ -5,6 +5,7 @@
namespace Microsoft.Azure.Cosmos.Linq
{
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq.Expressions;
using Microsoft.Azure.Cosmos;
@ -49,6 +50,12 @@ namespace Microsoft.Azure.Cosmos.Linq
if (methodCallExpression.Method.DeclaringType.GeUnderlyingSystemType() == typeof(CosmosLinqExtensions))
{
// CosmosLinq Extensions are either RegexMatch or Type check functions (IsString, IsBool, etc.)
if (methodCallExpression.Method.Name == nameof(CosmosLinqExtensions.RegexMatch))
{
return StringBuiltinFunctions.Visit(methodCallExpression, context);
}
return TypeCheckFunctions.Visit(methodCallExpression, context);
}
}

Просмотреть файл

@ -327,6 +327,43 @@ namespace Microsoft.Azure.Cosmos.Linq
}
}
private class RegexMatchVisitor : SqlBuiltinFunctionVisitor
{
public RegexMatchVisitor()
: base(SqlFunctionCallScalarExpression.Names.RegexMatch,
isStatic: true,
new List<Type[]>()
{
new Type[]{ typeof(object), typeof(string)}, // search string, regex pattern
new Type[]{ typeof(object), typeof(string), typeof(string)} // search string, regex pattern, search modifier
})
{
}
protected override SqlScalarExpression VisitImplicit(MethodCallExpression methodCallExpression, TranslationContext context)
{
int argumentCount = methodCallExpression.Arguments.Count;
if (argumentCount == 0 || argumentCount > 3 || (methodCallExpression.Arguments[1].NodeType != ExpressionType.Constant))
{
return null;
}
List<SqlScalarExpression> arguments = new List<SqlScalarExpression>
{
// Argument 0 and the Method object is the same, since Regex is an extension method
ExpressionToSql.VisitNonSubqueryScalarExpression(methodCallExpression.Arguments[0], context),
ExpressionToSql.VisitNonSubqueryScalarExpression(methodCallExpression.Arguments[1], context)
};
if (argumentCount > 2 && (methodCallExpression.Arguments[2].NodeType == ExpressionType.Constant))
{
arguments.Add(ExpressionToSql.VisitNonSubqueryScalarExpression(methodCallExpression.Arguments[2], context));
}
return SqlFunctionCallScalarExpression.CreateBuiltin(SqlFunctionCallScalarExpression.Names.RegexMatch, arguments.ToArray());
}
}
private class StringVisitToString : SqlBuiltinFunctionVisitor
{
public StringVisitToString()
@ -432,6 +469,10 @@ namespace Microsoft.Azure.Cosmos.Linq
"TrimStart",
new StringVisitTrimStart()
},
{
nameof(CosmosLinqExtensions.RegexMatch),
new RegexMatchVisitor()
},
{
"Replace",
new SqlBuiltinFunctionVisitor(SqlFunctionCallScalarExpression.Names.Replace,

Просмотреть файл

@ -10,6 +10,7 @@ namespace Microsoft.Azure.Cosmos.Linq
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos.Diagnostics;
@ -175,6 +176,49 @@ namespace Microsoft.Azure.Cosmos.Linq
throw new NotImplementedException(ClientResources.TypeCheckExtensionFunctionsNotImplemented);
}
/// <summary>
/// Returns a Boolean value indicating if the specified expression matches the supplied regex pattern.
/// For more information, see https://learn.microsoft.com/en-us/azure/cosmos-db/nosql/query/regexmatch.
/// This method is to be used in LINQ expressions only and will be evaluated on server.
/// There's no implementation provided in the client library.
/// </summary>
/// <param name="obj"></param>
/// <param name="regularExpression">A string expression with a regular expression defined to use when searching.</param>
/// <returns>Returns true if the string matches the regex expressions; otherwise, false.</returns>
/// <example>
/// <code>
/// <![CDATA[
/// var matched = documents.Where(document => document.Name.RegexMatch(<regex>));
/// ]]>
/// </code>
/// </example>
public static bool RegexMatch(this object obj, string regularExpression)
{
throw new NotImplementedException(ClientResources.TypeCheckExtensionFunctionsNotImplemented);
}
/// <summary>
/// Returns a Boolean value indicating if the specified expression matches the supplied regex pattern.
/// For more information, see https://learn.microsoft.com/en-us/azure/cosmos-db/nosql/query/regexmatch.
/// This method is to be used in LINQ expressions only and will be evaluated on server.
/// There's no implementation provided in the client library.
/// </summary>
/// <param name="obj"></param>
/// <param name="regularExpression">A string expression with a regular expression defined to use when searching.</param>
/// <param name="searchModifier">An optional string expression with the selected modifiers to use with the regular expression.</param>
/// <returns>Returns true if the string matches the regex expressions; otherwise, false.</returns>
/// <example>
/// <code>
/// <![CDATA[
/// var matched = documents.Where(document => document.Name.RegexMatch(<regex>, <search_modifier>));
/// ]]>
/// </code>
/// </example>
public static bool RegexMatch(this object obj, string regularExpression, string searchModifier)
{
throw new NotImplementedException(ClientResources.TypeCheckExtensionFunctionsNotImplemented);
}
/// <summary>
/// This method generate query definition from LINQ query.
/// </summary>

Просмотреть файл

@ -112,6 +112,7 @@ namespace Microsoft.Azure.Cosmos.SqlObjects
{ Names.Power, Identifiers.Power },
{ Names.Radians, Identifiers.Radians },
{ Names.Rand, Identifiers.Rand },
{ Names.RegexMatch, Identifiers.RegexMatch },
{ Names.Replace, Identifiers.Replace },
{ Names.Replicate, Identifiers.Replicate },
{ Names.Reverse, Identifiers.Reverse },
@ -332,6 +333,7 @@ namespace Microsoft.Azure.Cosmos.SqlObjects
public const string Power = "POWER";
public const string Radians = "RADIANS";
public const string Rand = "RAND";
public const string RegexMatch = "RegexMatch";
public const string Replace = "REPLACE";
public const string Replicate = "REPLICATE";
public const string Reverse = "REVERSE";
@ -474,6 +476,7 @@ namespace Microsoft.Azure.Cosmos.SqlObjects
public static readonly SqlIdentifier Power = SqlIdentifier.Create(Names.Power);
public static readonly SqlIdentifier Radians = SqlIdentifier.Create(Names.Radians);
public static readonly SqlIdentifier Rand = SqlIdentifier.Create(Names.Rand);
public static readonly SqlIdentifier RegexMatch = SqlIdentifier.Create(Names.RegexMatch);
public static readonly SqlIdentifier Replace = SqlIdentifier.Create(Names.Replace);
public static readonly SqlIdentifier Replicate = SqlIdentifier.Create(Names.Replicate);
public static readonly SqlIdentifier Reverse = SqlIdentifier.Create(Names.Reverse);

Просмотреть файл

@ -0,0 +1,170 @@
<Results>
<Result>
<Input>
<Description><![CDATA[RegexMatch with 1 argument]]></Description>
<Expression><![CDATA[query.Where(doc => doc.StringField.RegexMatch("abcd"))]]></Expression>
</Input>
<Output>
<SqlQuery><![CDATA[
SELECT VALUE root
FROM root
WHERE RegexMatch(root["StringField"], "abcd")]]></SqlQuery>
</Output>
</Result>
<Result>
<Input>
<Description><![CDATA[RegexMatch with 2 argument]]></Description>
<Expression><![CDATA[query.Where(doc => doc.StringField.RegexMatch("abcd", "i"))]]></Expression>
</Input>
<Output>
<SqlQuery><![CDATA[
SELECT VALUE root
FROM root
WHERE RegexMatch(root["StringField"], "abcd", "i")]]></SqlQuery>
</Output>
</Result>
<Result>
<Input>
<Description><![CDATA[RegexMatch with 1st argument member expression]]></Description>
<Expression><![CDATA[query.Where(doc => doc.StringField.RegexMatch(doc.StringField2))]]></Expression>
</Input>
<Output>
<SqlQuery><![CDATA[
SELECT VALUE root
FROM root
WHERE RegexMatch(root["StringField"], root["StringField2"])]]></SqlQuery>
</Output>
</Result>
<Result>
<Input>
<Description><![CDATA[RegexMatch with ToString]]></Description>
<Expression><![CDATA[query.Where(doc => doc.StringField.RegexMatch(doc.IntField.ToString()))]]></Expression>
</Input>
<Output>
<SqlQuery><![CDATA[
SELECT VALUE root
FROM root
WHERE RegexMatch(root["StringField"], ToString(root["IntField"]))]]></SqlQuery>
</Output>
</Result>
<Result>
<Input>
<Description><![CDATA[RegexMatch with StringUpper]]></Description>
<Expression><![CDATA[query.Where(doc => doc.StringField.RegexMatch(doc.StringField2.ToUpper()))]]></Expression>
</Input>
<Output>
<SqlQuery><![CDATA[
SELECT VALUE root
FROM root
WHERE RegexMatch(root["StringField"], UPPER(root["StringField2"]))]]></SqlQuery>
</Output>
</Result>
<Result>
<Input>
<Description><![CDATA[RegexMatch with StringLower]]></Description>
<Expression><![CDATA[query.Where(doc => doc.StringField.RegexMatch(doc.StringField2.ToLower()))]]></Expression>
</Input>
<Output>
<SqlQuery><![CDATA[
SELECT VALUE root
FROM root
WHERE RegexMatch(root["StringField"], LOWER(root["StringField2"]))]]></SqlQuery>
</Output>
</Result>
<Result>
<Input>
<Description><![CDATA[RegexMatch with StringConcat]]></Description>
<Expression><![CDATA[query.Where(doc => doc.StringField.RegexMatch(Concat(doc.StringField, "str")))]]></Expression>
</Input>
<Output>
<SqlQuery><![CDATA[
SELECT VALUE root
FROM root
WHERE RegexMatch(root["StringField"], CONCAT(root["StringField"], "str"))]]></SqlQuery>
</Output>
</Result>
<Result>
<Input>
<Description><![CDATA[RegexMatch with string composition]]></Description>
<Expression><![CDATA[query.Where(doc => doc.IntField.ToString().RegexMatch(doc.StringField))]]></Expression>
</Input>
<Output>
<SqlQuery><![CDATA[
SELECT VALUE root
FROM root
WHERE RegexMatch(ToString(root["IntField"]), root["StringField"])]]></SqlQuery>
</Output>
</Result>
<Result>
<Input>
<Description><![CDATA[RegexMatch with string composition 2]]></Description>
<Expression><![CDATA[query.Where(doc => doc.IntField.ToString().RegexMatch(doc.StringField, doc.StringField2.ToString()))]]></Expression>
</Input>
<Output>
<SqlQuery><![CDATA[
SELECT VALUE root
FROM root
WHERE RegexMatch(ToString(root["IntField"]), root["StringField"], root["StringField2"])]]></SqlQuery>
</Output>
</Result>
<Result>
<Input>
<Description><![CDATA[RegexMatch with conditional]]></Description>
<Expression><![CDATA[query.Where(doc => (doc.StringField.RegexMatch("abc") AndAlso doc.StringField2.RegexMatch("def")))]]></Expression>
</Input>
<Output>
<SqlQuery><![CDATA[
SELECT VALUE root
FROM root
WHERE (RegexMatch(root["StringField"], "abc") AND RegexMatch(root["StringField2"], "def"))]]></SqlQuery>
</Output>
</Result>
<Result>
<Input>
<Description><![CDATA[RegexMatch with conditional 2]]></Description>
<Expression><![CDATA[query.Where(doc => (doc.StringField.RegexMatch("abc") OrElse doc.StringField2.RegexMatch("def")))]]></Expression>
</Input>
<Output>
<SqlQuery><![CDATA[
SELECT VALUE root
FROM root
WHERE (RegexMatch(root["StringField"], "abc") OR RegexMatch(root["StringField2"], "def"))]]></SqlQuery>
</Output>
</Result>
<Result>
<Input>
<Description><![CDATA[RegexMatch with conditional 3]]></Description>
<Expression><![CDATA[query.Where(doc => doc.StringField.RegexMatch("abc")).Where(doc => doc.StringField2.RegexMatch("abc"))]]></Expression>
</Input>
<Output>
<SqlQuery><![CDATA[
SELECT VALUE root
FROM root
WHERE (RegexMatch(root["StringField"], "abc") AND RegexMatch(root["StringField2"], "abc"))]]></SqlQuery>
</Output>
</Result>
<Result>
<Input>
<Description><![CDATA[RegexMatch with conditional 4]]></Description>
<Expression><![CDATA[query.Where(doc => doc.StringField.RegexMatch("abc")).Where(doc => Not(doc.StringField2.RegexMatch("abc")))]]></Expression>
</Input>
<Output>
<SqlQuery><![CDATA[
SELECT VALUE root
FROM root
WHERE (RegexMatch(root["StringField"], "abc") AND (NOT RegexMatch(root["StringField2"], "abc")))]]></SqlQuery>
</Output>
</Result>
<Result>
<Input>
<Description><![CDATA[RegexMatch with 2nd argument invalid string options]]></Description>
<Expression><![CDATA[query.Where(doc => doc.StringField.RegexMatch("abcd", "this should error out on the back end"))]]></Expression>
</Input>
<Output>
<SqlQuery><![CDATA[
SELECT VALUE root
FROM root
WHERE RegexMatch(root["StringField"], "abcd", "this should error out on the back end")]]></SqlQuery>
</Output>
</Result>
</Results>

Просмотреть файл

@ -5,11 +5,9 @@
<Expression><![CDATA[query.Select(doc => (Compare(doc.StringField, doc.StringField2) == 0))]]></Expression>
</Input>
<Output>
<SqlQuery>
<![CDATA[
SELECT VALUE (root["StringField"] = root["StringField2"])
FROM root]]>
</SqlQuery>
<SqlQuery><![CDATA[
SELECT VALUE (root["StringField"] = root["StringField2"])
FROM root]]></SqlQuery>
</Output>
</Result>
<Result>
@ -18,11 +16,9 @@ FROM root]]>
<Expression><![CDATA[query.Select(doc => (Compare(doc.StringField, doc.StringField2) > 0))]]></Expression>
</Input>
<Output>
<SqlQuery>
<![CDATA[
SELECT VALUE (root["StringField"] > root["StringField2"])
FROM root]]>
</SqlQuery>
<SqlQuery><![CDATA[
SELECT VALUE (root["StringField"] > root["StringField2"])
FROM root]]></SqlQuery>
</Output>
</Result>
<Result>
@ -31,11 +27,9 @@ FROM root]]>
<Expression><![CDATA[query.Select(doc => (Compare(doc.StringField, doc.StringField2) >= 0))]]></Expression>
</Input>
<Output>
<SqlQuery>
<![CDATA[
SELECT VALUE (root["StringField"] >= root["StringField2"])
FROM root]]>
</SqlQuery>
<SqlQuery><![CDATA[
SELECT VALUE (root["StringField"] >= root["StringField2"])
FROM root]]></SqlQuery>
</Output>
</Result>
<Result>
@ -44,11 +38,9 @@ FROM root]]>
<Expression><![CDATA[query.Select(doc => (Compare(doc.StringField, doc.StringField2) < 0))]]></Expression>
</Input>
<Output>
<SqlQuery>
<![CDATA[
SELECT VALUE (root["StringField"] < root["StringField2"])
FROM root]]>
</SqlQuery>
<SqlQuery><![CDATA[
SELECT VALUE (root["StringField"] < root["StringField2"])
FROM root]]></SqlQuery>
</Output>
</Result>
<Result>
@ -57,11 +49,9 @@ FROM root]]>
<Expression><![CDATA[query.Select(doc => (Compare(doc.StringField, doc.StringField2) <= 0))]]></Expression>
</Input>
<Output>
<SqlQuery>
<![CDATA[
SELECT VALUE (root["StringField"] <= root["StringField2"])
FROM root]]>
</SqlQuery>
<SqlQuery><![CDATA[
SELECT VALUE (root["StringField"] <= root["StringField2"])
FROM root]]></SqlQuery>
</Output>
</Result>
<Result>
@ -70,11 +60,9 @@ FROM root]]>
<Expression><![CDATA[query.Select(doc => (Compare(doc.StringField, "str") == 0))]]></Expression>
</Input>
<Output>
<SqlQuery>
<![CDATA[
SELECT VALUE (root["StringField"] = "str")
FROM root]]>
</SqlQuery>
<SqlQuery><![CDATA[
SELECT VALUE (root["StringField"] = "str")
FROM root]]></SqlQuery>
</Output>
</Result>
<Result>
@ -83,11 +71,9 @@ FROM root]]>
<Expression><![CDATA[query.Select(doc => (Compare(doc.StringField, "str") > 0))]]></Expression>
</Input>
<Output>
<SqlQuery>
<![CDATA[
SELECT VALUE (root["StringField"] > "str")
FROM root]]>
</SqlQuery>
<SqlQuery><![CDATA[
SELECT VALUE (root["StringField"] > "str")
FROM root]]></SqlQuery>
</Output>
</Result>
<Result>
@ -96,11 +82,9 @@ FROM root]]>
<Expression><![CDATA[query.Select(doc => (Compare(doc.StringField, "str") >= 0))]]></Expression>
</Input>
<Output>
<SqlQuery>
<![CDATA[
SELECT VALUE (root["StringField"] >= "str")
FROM root]]>
</SqlQuery>
<SqlQuery><![CDATA[
SELECT VALUE (root["StringField"] >= "str")
FROM root]]></SqlQuery>
</Output>
</Result>
<Result>
@ -109,11 +93,9 @@ FROM root]]>
<Expression><![CDATA[query.Select(doc => (Compare(doc.StringField, "str") < 0))]]></Expression>
</Input>
<Output>
<SqlQuery>
<![CDATA[
SELECT VALUE (root["StringField"] < "str")
FROM root]]>
</SqlQuery>
<SqlQuery><![CDATA[
SELECT VALUE (root["StringField"] < "str")
FROM root]]></SqlQuery>
</Output>
</Result>
<Result>
@ -122,11 +104,9 @@ FROM root]]>
<Expression><![CDATA[query.Select(doc => (Compare(doc.StringField, "str") <= 0))]]></Expression>
</Input>
<Output>
<SqlQuery>
<![CDATA[
SELECT VALUE (root["StringField"] <= "str")
FROM root]]>
</SqlQuery>
<SqlQuery><![CDATA[
SELECT VALUE (root["StringField"] <= "str")
FROM root]]></SqlQuery>
</Output>
</Result>
<Result>
@ -135,11 +115,9 @@ FROM root]]>
<Expression><![CDATA[query.Select(doc => (0 == Compare(doc.StringField, doc.StringField2)))]]></Expression>
</Input>
<Output>
<SqlQuery>
<![CDATA[
SELECT VALUE (root["StringField"] = root["StringField2"])
FROM root]]>
</SqlQuery>
<SqlQuery><![CDATA[
SELECT VALUE (root["StringField"] = root["StringField2"])
FROM root]]></SqlQuery>
</Output>
</Result>
<Result>
@ -148,11 +126,9 @@ FROM root]]>
<Expression><![CDATA[query.Select(doc => (0 < Compare(doc.StringField, doc.StringField2)))]]></Expression>
</Input>
<Output>
<SqlQuery>
<![CDATA[
SELECT VALUE (root["StringField"] > root["StringField2"])
FROM root]]>
</SqlQuery>
<SqlQuery><![CDATA[
SELECT VALUE (root["StringField"] > root["StringField2"])
FROM root]]></SqlQuery>
</Output>
</Result>
<Result>
@ -161,11 +137,9 @@ FROM root]]>
<Expression><![CDATA[query.Select(doc => (0 <= Compare(doc.StringField, doc.StringField2)))]]></Expression>
</Input>
<Output>
<SqlQuery>
<![CDATA[
SELECT VALUE (root["StringField"] >= root["StringField2"])
FROM root]]>
</SqlQuery>
<SqlQuery><![CDATA[
SELECT VALUE (root["StringField"] >= root["StringField2"])
FROM root]]></SqlQuery>
</Output>
</Result>
<Result>
@ -174,11 +148,9 @@ FROM root]]>
<Expression><![CDATA[query.Select(doc => (0 > Compare(doc.StringField, doc.StringField2)))]]></Expression>
</Input>
<Output>
<SqlQuery>
<![CDATA[
SELECT VALUE (root["StringField"] < root["StringField2"])
FROM root]]>
</SqlQuery>
<SqlQuery><![CDATA[
SELECT VALUE (root["StringField"] < root["StringField2"])
FROM root]]></SqlQuery>
</Output>
</Result>
<Result>
@ -187,11 +159,9 @@ FROM root]]>
<Expression><![CDATA[query.Select(doc => (0 >= Compare(doc.StringField, doc.StringField2)))]]></Expression>
</Input>
<Output>
<SqlQuery>
<![CDATA[
SELECT VALUE (root["StringField"] <= root["StringField2"])
FROM root]]>
</SqlQuery>
<SqlQuery><![CDATA[
SELECT VALUE (root["StringField"] <= root["StringField2"])
FROM root]]></SqlQuery>
</Output>
</Result>
<Result>

Просмотреть файл

@ -291,6 +291,38 @@ namespace Microsoft.Azure.Cosmos.Services.Management.Tests.LinqProviderTests
this.ExecuteTestSuite(inputs);
}
[TestMethod]
public void TestRegexMatchFunction()
{
// Similar to the type checking function, RegexMatch are not supported client side.
// Therefore this method is verified with baseline only.
List<DataObject> data = new List<DataObject>();
IOrderedQueryable<DataObject> query = testContainer.GetItemLinqQueryable<DataObject>(allowSynchronousQueryExecution: true);
Func<bool, IQueryable<DataObject>> getQuery = useQuery => useQuery ? query : data.AsQueryable();
List<LinqTestInput> inputs = new List<LinqTestInput>
{
new LinqTestInput("RegexMatch with 1 argument", b => getQuery(b).Where(doc => doc.StringField.RegexMatch("abcd"))),
new LinqTestInput("RegexMatch with 2 argument", b => getQuery(b).Where(doc => doc.StringField.RegexMatch("abcd", "i"))),
new LinqTestInput("RegexMatch with 1st argument member expression", b => getQuery(b).Where(doc => doc.StringField.RegexMatch(doc.StringField2))),
new LinqTestInput("RegexMatch with ToString", b => getQuery(b).Where(doc => doc.StringField.RegexMatch(doc.IntField.ToString()))),
new LinqTestInput("RegexMatch with StringUpper", b => getQuery(b).Where(doc => doc.StringField.RegexMatch(doc.StringField2.ToUpper()))),
new LinqTestInput("RegexMatch with StringLower", b => getQuery(b).Where(doc => doc.StringField.RegexMatch(doc.StringField2.ToLower()))),
new LinqTestInput("RegexMatch with StringConcat", b => getQuery(b).Where(doc => doc.StringField.RegexMatch(string.Concat(doc.StringField, "str")))),
new LinqTestInput("RegexMatch with string composition", b => getQuery(b).Where(doc => doc.IntField.ToString().RegexMatch(doc.StringField))),
new LinqTestInput("RegexMatch with string composition 2", b => getQuery(b).Where(doc => doc.IntField.ToString().RegexMatch(doc.StringField, doc.StringField2.ToString()))),
new LinqTestInput("RegexMatch with conditional", b => getQuery(b).Where(doc => doc.StringField.RegexMatch("abc") && doc.StringField2.RegexMatch("def"))),
new LinqTestInput("RegexMatch with conditional 2", b => getQuery(b).Where(doc => doc.StringField.RegexMatch("abc") || doc.StringField2.RegexMatch("def"))),
new LinqTestInput("RegexMatch with conditional 3", b => getQuery(b).Where(doc => doc.StringField.RegexMatch("abc")).Where(doc => doc.StringField2.RegexMatch("abc"))),
new LinqTestInput("RegexMatch with conditional 4", b => getQuery(b).Where(doc => doc.StringField.RegexMatch("abc")).Where(doc => !doc.StringField2.RegexMatch("abc"))),
new LinqTestInput("RegexMatch with 2nd argument invalid string options", b => getQuery(b).Where(doc => doc.StringField.RegexMatch("abcd", "this should error out on the back end"))),
};
this.ExecuteTestSuite(inputs);
}
[TestMethod]
public void TestMemberInitializer()
{

Просмотреть файл

@ -202,6 +202,9 @@
<Content Include="BaselineTest\TestBaseline\LinqTranslationBaselineTests.TestMemberAccessWithNullableTypes.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="BaselineTest\TestBaseline\LinqTranslationBaselineTests.TestRegexMatchFunction.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="BaselineTest\TestBaseline\LinqTranslationBaselineTests.TestSelectTop.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

Просмотреть файл

@ -5367,6 +5367,20 @@
],
"MethodInfo": "Boolean IsString(System.Object);IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
},
"Boolean RegexMatch(System.Object, System.String, System.String)[System.Runtime.CompilerServices.ExtensionAttribute()]": {
"Type": "Method",
"Attributes": [
"ExtensionAttribute"
],
"MethodInfo": "Boolean RegexMatch(System.Object, System.String, System.String);IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
},
"Boolean RegexMatch(System.Object, System.String)[System.Runtime.CompilerServices.ExtensionAttribute()]": {
"Type": "Method",
"Attributes": [
"ExtensionAttribute"
],
"MethodInfo": "Boolean RegexMatch(System.Object, System.String);IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
},
"Microsoft.Azure.Cosmos.FeedIterator ToStreamIterator[T](System.Linq.IQueryable`1[T])[System.Runtime.CompilerServices.ExtensionAttribute()]": {
"Type": "Method",
"Attributes": [