diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteMethodCallTranslatorProvider.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteMethodCallTranslatorProvider.cs
index f35640cacc7..9f1660c5a0c 100644
--- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteMethodCallTranslatorProvider.cs
+++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteMethodCallTranslatorProvider.cs
@@ -31,7 +31,7 @@ public SqliteMethodCallTranslatorProvider([NotNull] RelationalMethodCallTranslat
new SqliteByteArrayMethodTranslator(sqlExpressionFactory),
new SqliteDateTimeAddTranslator(sqlExpressionFactory),
new SqliteMathTranslator(sqlExpressionFactory),
- new SqliteRegexTranslator(sqlExpressionFactory),
+ new SqliteRegexMethodTranslator(sqlExpressionFactory),
new SqliteStringMethodTranslator(sqlExpressionFactory)
});
}
diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteRegexTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteRegexMethodTranslator.cs
similarity index 78%
rename from src/EFCore.Sqlite.Core/Query/Internal/SqliteRegexTranslator.cs
rename to src/EFCore.Sqlite.Core/Query/Internal/SqliteRegexMethodTranslator.cs
index 8fee6f50889..29ed462f610 100644
--- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteRegexTranslator.cs
+++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteRegexMethodTranslator.cs
@@ -19,10 +19,12 @@ namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
///
- public class SqliteRegexTranslator : IMethodCallTranslator
+ public class SqliteRegexMethodTranslator : IMethodCallTranslator
{
+ private readonly static MethodInfo _regexIsMatchMethodInfo
+ = typeof(Regex).GetRuntimeMethod(nameof(Regex.IsMatch), new Type[] { typeof(string), typeof(string) });
+
private readonly ISqlExpressionFactory _sqlExpressionFactory;
- private readonly static MethodInfo regexIsMatchMethod = typeof(Regex).GetMethod(nameof(Regex.IsMatch), new Type[] { typeof(string), typeof(string) });
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
@@ -30,17 +32,21 @@ public class SqliteRegexTranslator : IMethodCallTranslator
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
///
- public SqliteRegexTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory)
+ public SqliteRegexMethodTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory)
{
+ Check.NotNull(sqlExpressionFactory, nameof(sqlExpressionFactory));
+
_sqlExpressionFactory = sqlExpressionFactory;
}
+
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
///
- public virtual SqlExpression Translate(SqlExpression instance,
+ public virtual SqlExpression Translate(
+ SqlExpression instance,
MethodInfo method,
IReadOnlyList arguments,
IDiagnosticsLogger logger)
@@ -49,13 +55,13 @@ public virtual SqlExpression Translate(SqlExpression instance,
Check.NotNull(arguments, nameof(arguments));
Check.NotNull(logger, nameof(logger));
-
- if (method.Equals(regexIsMatchMethod))
+ if (method.Equals(_regexIsMatchMethodInfo))
{
- return _sqlExpressionFactory.Function("regexp",
+ return _sqlExpressionFactory.Function(
+ "regexp",
new[] { arguments[1], arguments[0] },
- false,
- new[] { false, false },
+ nullable: true,
+ argumentsPropagateNullability: new[] { true, true },
typeof(bool),
arguments[0].TypeMapping);
}
diff --git a/src/EFCore.Sqlite.Core/Storage/Internal/SqliteRelationalConnection.cs b/src/EFCore.Sqlite.Core/Storage/Internal/SqliteRelationalConnection.cs
index a78fce5a056..1d32e86e7fc 100644
--- a/src/EFCore.Sqlite.Core/Storage/Internal/SqliteRelationalConnection.cs
+++ b/src/EFCore.Sqlite.Core/Storage/Internal/SqliteRelationalConnection.cs
@@ -115,13 +115,14 @@ private void InitializeDbConnection(DbConnection connection)
sqliteConnection.DefaultTimeout = _commandTimeout.Value;
}
- sqliteConnection.CreateFunction(
+ sqliteConnection.CreateFunction(
"regexp",
(pattern, input) =>
{
- if (input == null || pattern == null)
+ if (input == null
+ || pattern == null)
{
- return false;
+ return null;
}
return Regex.IsMatch(input, pattern);
@@ -146,7 +147,8 @@ private void InitializeDbConnection(DbConnection connection)
return Convert.ToDouble(dividend, CultureInfo.InvariantCulture)
% Convert.ToDouble(divisor, CultureInfo.InvariantCulture);
- });
+ },
+ isDeterministic: true);
sqliteConnection.CreateFunction(
name: "ef_add",
@@ -176,7 +178,6 @@ private void InitializeDbConnection(DbConnection connection)
isDeterministic: true);
}
else
-
{
_logger.UnexpectedConnectionTypeWarning(connection.GetType());
}
diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindFunctionsQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindFunctionsQueryCosmosTest.cs
index 5937253d50f..5452c1928f8 100644
--- a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindFunctionsQueryCosmosTest.cs
+++ b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindFunctionsQueryCosmosTest.cs
@@ -1049,6 +1049,11 @@ public override Task Int_Compare_to_simple_zero(bool async)
return base.Int_Compare_to_simple_zero(async);
}
+ public override Task Regex_IsMatch_MethodCall(bool async)
+ {
+ return AssertTranslationFailed(() => base.Regex_IsMatch_MethodCall(async));
+ }
+
private void AssertSql(params string[] expected)
=> Fixture.TestSqlLoggerFactory.AssertBaseline(expected);
diff --git a/test/EFCore.Specification.Tests/Query/NorthwindFunctionsQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/NorthwindFunctionsQueryTestBase.cs
index 52788059cd2..57b86da8d3f 100644
--- a/test/EFCore.Specification.Tests/Query/NorthwindFunctionsQueryTestBase.cs
+++ b/test/EFCore.Specification.Tests/Query/NorthwindFunctionsQueryTestBase.cs
@@ -1590,7 +1590,8 @@ public virtual Task Projecting_Math_Truncate_and_ordering_by_it_twice3(bool asyn
[MemberData(nameof(IsAsyncData))]
public virtual Task Regex_IsMatch_MethodCall(bool async)
{
- return AssertQuery(async,
+ return AssertQuery(
+ async,
ss => ss.Set().Where(o => Regex.IsMatch(o.CustomerID, @"^T")),
entryCount: 6);
}
diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindFunctionsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindFunctionsQuerySqlServerTest.cs
index 130c6256bbc..630e0e6b822 100644
--- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindFunctionsQuerySqlServerTest.cs
+++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindFunctionsQuerySqlServerTest.cs
@@ -1548,6 +1548,7 @@ public override async Task Projecting_Math_Truncate_and_ordering_by_it_twice3(bo
//WHERE [o].[OrderID] < 10250
//ORDER BY [A] DESC");
}
+
public override Task Regex_IsMatch_MethodCall(bool async)
{
return AssertTranslationFailed(() => base.Regex_IsMatch_MethodCall(async));