From 4b94ab372f45ff4c3d4d87db5bff318ef45e1f5e Mon Sep 17 00:00:00 2001 From: LeaFrock Date: Mon, 16 May 2022 20:53:22 +0800 Subject: [PATCH] Optimize `string.IndexOf(string, int)` translation when `startIndex` is a constant --- .../MySqlStringComparisonMethodTranslator.cs | 9 ++++++--- .../NorthwindFunctionsQueryMySqlTest.MySql.cs | 17 ++++++++++++++++- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/EFCore.MySql/Query/ExpressionTranslators/Internal/MySqlStringComparisonMethodTranslator.cs b/src/EFCore.MySql/Query/ExpressionTranslators/Internal/MySqlStringComparisonMethodTranslator.cs index 0a53facf1..92de70a72 100644 --- a/src/EFCore.MySql/Query/ExpressionTranslators/Internal/MySqlStringComparisonMethodTranslator.cs +++ b/src/EFCore.MySql/Query/ExpressionTranslators/Internal/MySqlStringComparisonMethodTranslator.cs @@ -622,9 +622,12 @@ private SqlExpression CharLength(SqlExpression value) private SqlExpression Locate(SqlExpression sub, SqlExpression str, SqlExpression startIndex = null) { - var args = startIndex is null - ? new SqlExpression[] { sub, str } - : new SqlExpression[] { sub, str, _sqlExpressionFactory.Add(startIndex, _sqlExpressionFactory.Constant(1)) }; + var args = startIndex switch + { + null => new SqlExpression[] { sub, str }, + SqlConstantExpression { Value:int idx } => new SqlExpression[] { sub, str, _sqlExpressionFactory.Constant(idx + 1) }, + _ => new SqlExpression[] { sub, str, _sqlExpressionFactory.Add(startIndex, _sqlExpressionFactory.Constant(1)) } + }; return _sqlExpressionFactory.NullableFunction("LOCATE", args, typeof(int)); } diff --git a/test/EFCore.MySql.FunctionalTests/Query/NorthwindFunctionsQueryMySqlTest.MySql.cs b/test/EFCore.MySql.FunctionalTests/Query/NorthwindFunctionsQueryMySqlTest.MySql.cs index fe7640637..06330029d 100644 --- a/test/EFCore.MySql.FunctionalTests/Query/NorthwindFunctionsQueryMySqlTest.MySql.cs +++ b/test/EFCore.MySql.FunctionalTests/Query/NorthwindFunctionsQueryMySqlTest.MySql.cs @@ -705,12 +705,27 @@ ELSE LOCATE(CONVERT(LCASE('nt') USING utf8mb4) COLLATE utf8mb4_bin, LCASE(`c`.`C END = 1"); } + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public async Task StringIndexOf_with_constant_start_index(bool async) + { + await AssertQuery( + async, + ss => ss.Set().Where(c => c.CustomerID.IndexOf("nt", 0, StringComparison.OrdinalIgnoreCase) == 1), + entryCount: 1); + + AssertSql( + @"SELECT `c`.`CustomerID`, `c`.`Address`, `c`.`City`, `c`.`CompanyName`, `c`.`ContactName`, `c`.`ContactTitle`, `c`.`Country`, `c`.`Fax`, `c`.`Phone`, `c`.`PostalCode`, `c`.`Region` +FROM `Customers` AS `c` +WHERE (LOCATE(CONVERT(LCASE('nt') USING utf8mb4) COLLATE utf8mb4_bin, LCASE(`c`.`CustomerID`), 1) - 1) = 1"); + } + [ConditionalTheory] [InlineData(0, 1, false)] [InlineData(2, 0, false)] [InlineData(0, 1, true)] [InlineData(2, 0, true)] - public async Task StringIndexOf_with_start_index(int startIndex, int expected, bool async) + public async Task StringIndexOf_with_parameter_start_index(int startIndex, int expected, bool async) { await AssertQuery( async,