Skip to content

Commit bb6cc99

Browse files
committed
Add method postfix when rewriting parameters for StartsWith/EndsWith/Contains
Fixes dotnet#32432
1 parent d79cd19 commit bb6cc99

10 files changed

+183
-130
lines changed

src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitor.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System.Diagnostics.CodeAnalysis;
5+
using System.Globalization;
56
using System.Text;
67
using Microsoft.EntityFrameworkCore.Query.SqlExpressions;
78
using ExpressionExtensions = Microsoft.EntityFrameworkCore.Query.ExpressionExtensions;
@@ -279,7 +280,8 @@ when patternParameter.Name.StartsWith(QueryCompilationContext.QueryParameterPref
279280
QueryCompilationContext.QueryContextParameter);
280281

281282
var escapedPatternParameter =
282-
_queryCompilationContext.RegisterRuntimeParameter(patternParameter.Name + "_rewritten", lambda);
283+
_queryCompilationContext.RegisterRuntimeParameter(
284+
$"{patternParameter.Name}_{methodType.ToString().ToLower(CultureInfo.InvariantCulture)}", lambda);
283285

284286
translation = _sqlExpressionFactory.Like(
285287
translatedInstance,

src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitor.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,8 @@ when patternParameter.Name.StartsWith(QueryCompilationContext.QueryParameterPref
329329
QueryCompilationContext.QueryContextParameter);
330330

331331
var escapedPatternParameter =
332-
_queryCompilationContext.RegisterRuntimeParameter(patternParameter.Name + "_rewritten", lambda);
332+
_queryCompilationContext.RegisterRuntimeParameter(
333+
$"{patternParameter.Name}_{(startsWith ? "startswith" : "endswith")}", lambda);
333334

334335
translation = _sqlExpressionFactory.Like(
335336
translatedInstance,

test/EFCore.Specification.Tests/Query/FunkyDataQueryTestBase.cs

+15
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,21 @@ public virtual Task String_FirstOrDefault_and_LastOrDefault(bool async)
542542
AssertEqual(e.last, a.last);
543543
});
544544

545+
546+
[ConditionalTheory] // #32432
547+
[MemberData(nameof(IsAsyncData))]
548+
public virtual Task String_Contains_and_StartsWith_with_same_parameter(bool async)
549+
{
550+
var s = "B";
551+
552+
return AssertQuery(
553+
async,
554+
ss => ss.Set<FunkyCustomer>().Where(
555+
c => c.FirstName.Contains(s) || c.LastName.StartsWith(s)),
556+
ss => ss.Set<FunkyCustomer>().Where(
557+
c => c.FirstName.MaybeScalar(f => f.Contains(s)) == true || c.LastName.MaybeScalar(l => l.StartsWith(s)) == true));
558+
}
559+
545560
protected FunkyDataContext CreateContext()
546561
=> Fixture.CreateContext();
547562

test/EFCore.SqlServer.FunctionalTests/Query/FunkyDataQuerySqlServerTest.cs

+87-72
Original file line numberDiff line numberDiff line change
@@ -78,19 +78,19 @@ public override async Task String_contains_on_argument_with_wildcard_parameter(b
7878

7979
AssertSql(
8080
"""
81-
@__prm1_0_rewritten='%\%B%' (Size = 4000)
81+
@__prm1_0_contains='%\%B%' (Size = 4000)
8282
8383
SELECT [f].[FirstName]
8484
FROM [FunkyCustomers] AS [f]
85-
WHERE [f].[FirstName] LIKE @__prm1_0_rewritten ESCAPE N'\'
85+
WHERE [f].[FirstName] LIKE @__prm1_0_contains ESCAPE N'\'
8686
""",
8787
//
8888
"""
89-
@__prm2_0_rewritten='%a\_%' (Size = 4000)
89+
@__prm2_0_contains='%a\_%' (Size = 4000)
9090
9191
SELECT [f].[FirstName]
9292
FROM [FunkyCustomers] AS [f]
93-
WHERE [f].[FirstName] LIKE @__prm2_0_rewritten ESCAPE N'\'
93+
WHERE [f].[FirstName] LIKE @__prm2_0_contains ESCAPE N'\'
9494
""",
9595
//
9696
"""
@@ -100,35 +100,35 @@ FROM [FunkyCustomers] AS [f]
100100
""",
101101
//
102102
"""
103-
@__prm4_0_rewritten='%' (Size = 4000)
103+
@__prm4_0_contains='%' (Size = 4000)
104104
105105
SELECT [f].[FirstName]
106106
FROM [FunkyCustomers] AS [f]
107-
WHERE [f].[FirstName] LIKE @__prm4_0_rewritten ESCAPE N'\'
107+
WHERE [f].[FirstName] LIKE @__prm4_0_contains ESCAPE N'\'
108108
""",
109109
//
110110
"""
111-
@__prm5_0_rewritten='%\_Ba\_%' (Size = 4000)
111+
@__prm5_0_contains='%\_Ba\_%' (Size = 4000)
112112
113113
SELECT [f].[FirstName]
114114
FROM [FunkyCustomers] AS [f]
115-
WHERE [f].[FirstName] LIKE @__prm5_0_rewritten ESCAPE N'\'
115+
WHERE [f].[FirstName] LIKE @__prm5_0_contains ESCAPE N'\'
116116
""",
117117
//
118118
"""
119-
@__prm6_0_rewritten='%\%B\%a\%r%' (Size = 4000)
119+
@__prm6_0_contains='%\%B\%a\%r%' (Size = 4000)
120120
121121
SELECT [f].[FirstName]
122122
FROM [FunkyCustomers] AS [f]
123-
WHERE [f].[FirstName] NOT LIKE @__prm6_0_rewritten ESCAPE N'\' OR [f].[FirstName] IS NULL
123+
WHERE [f].[FirstName] NOT LIKE @__prm6_0_contains ESCAPE N'\' OR [f].[FirstName] IS NULL
124124
""",
125125
//
126126
"""
127-
@__prm7_0_rewritten='%' (Size = 4000)
127+
@__prm7_0_contains='%' (Size = 4000)
128128
129129
SELECT [f].[FirstName]
130130
FROM [FunkyCustomers] AS [f]
131-
WHERE [f].[FirstName] NOT LIKE @__prm7_0_rewritten ESCAPE N'\' OR [f].[FirstName] IS NULL
131+
WHERE [f].[FirstName] NOT LIKE @__prm7_0_contains ESCAPE N'\' OR [f].[FirstName] IS NULL
132132
""",
133133
//
134134
"""
@@ -221,61 +221,61 @@ public override async Task String_starts_with_on_argument_with_wildcard_paramete
221221
await base.String_starts_with_on_argument_with_wildcard_parameter(async);
222222

223223
AssertSql(
224-
"""
225-
@__prm1_0_rewritten='\%B%' (Size = 4000)
224+
"""
225+
@__prm1_0_startswith='\%B%' (Size = 4000)
226226
227227
SELECT [f].[FirstName]
228228
FROM [FunkyCustomers] AS [f]
229-
WHERE [f].[FirstName] LIKE @__prm1_0_rewritten ESCAPE N'\'
229+
WHERE [f].[FirstName] LIKE @__prm1_0_startswith ESCAPE N'\'
230230
""",
231-
//
232-
"""
233-
@__prm2_0_rewritten='\_B%' (Size = 4000)
231+
//
232+
"""
233+
@__prm2_0_startswith='\_B%' (Size = 4000)
234234
235235
SELECT [f].[FirstName]
236236
FROM [FunkyCustomers] AS [f]
237-
WHERE [f].[FirstName] LIKE @__prm2_0_rewritten ESCAPE N'\'
237+
WHERE [f].[FirstName] LIKE @__prm2_0_startswith ESCAPE N'\'
238238
""",
239-
//
240-
"""
239+
//
240+
"""
241241
SELECT [f].[FirstName]
242242
FROM [FunkyCustomers] AS [f]
243243
WHERE 0 = 1
244244
""",
245-
//
246-
"""
247-
@__prm4_0_rewritten='%' (Size = 4000)
245+
//
246+
"""
247+
@__prm4_0_startswith='%' (Size = 4000)
248248
249249
SELECT [f].[FirstName]
250250
FROM [FunkyCustomers] AS [f]
251-
WHERE [f].[FirstName] LIKE @__prm4_0_rewritten ESCAPE N'\'
251+
WHERE [f].[FirstName] LIKE @__prm4_0_startswith ESCAPE N'\'
252252
""",
253-
//
254-
"""
255-
@__prm5_0_rewritten='\_Ba\_%' (Size = 4000)
253+
//
254+
"""
255+
@__prm5_0_startswith='\_Ba\_%' (Size = 4000)
256256
257257
SELECT [f].[FirstName]
258258
FROM [FunkyCustomers] AS [f]
259-
WHERE [f].[FirstName] LIKE @__prm5_0_rewritten ESCAPE N'\'
259+
WHERE [f].[FirstName] LIKE @__prm5_0_startswith ESCAPE N'\'
260260
""",
261-
//
262-
"""
263-
@__prm6_0_rewritten='\%B\%a\%r%' (Size = 4000)
261+
//
262+
"""
263+
@__prm6_0_startswith='\%B\%a\%r%' (Size = 4000)
264264
265265
SELECT [f].[FirstName]
266266
FROM [FunkyCustomers] AS [f]
267-
WHERE [f].[FirstName] NOT LIKE @__prm6_0_rewritten ESCAPE N'\' OR [f].[FirstName] IS NULL
267+
WHERE [f].[FirstName] NOT LIKE @__prm6_0_startswith ESCAPE N'\' OR [f].[FirstName] IS NULL
268268
""",
269-
//
270-
"""
271-
@__prm7_0_rewritten='%' (Size = 4000)
269+
//
270+
"""
271+
@__prm7_0_startswith='%' (Size = 4000)
272272
273273
SELECT [f].[FirstName]
274274
FROM [FunkyCustomers] AS [f]
275-
WHERE [f].[FirstName] NOT LIKE @__prm7_0_rewritten ESCAPE N'\' OR [f].[FirstName] IS NULL
275+
WHERE [f].[FirstName] NOT LIKE @__prm7_0_startswith ESCAPE N'\' OR [f].[FirstName] IS NULL
276276
""",
277-
//
278-
"""
277+
//
278+
"""
279279
SELECT [f].[FirstName]
280280
FROM [FunkyCustomers] AS [f]
281281
""");
@@ -305,27 +305,27 @@ WHERE [f].[FirstName] LIKE N'B\[\[a^%' ESCAPE N'\'
305305
""",
306306
//
307307
"""
308-
@__prm1_0_rewritten='\[%' (Size = 4000)
308+
@__prm1_0_startswith='\[%' (Size = 4000)
309309
310310
SELECT [f].[Id], [f].[FirstName], [f].[LastName], [f].[NullableBool]
311311
FROM [FunkyCustomers] AS [f]
312-
WHERE [f].[FirstName] LIKE @__prm1_0_rewritten ESCAPE N'\'
312+
WHERE [f].[FirstName] LIKE @__prm1_0_startswith ESCAPE N'\'
313313
""",
314314
//
315315
"""
316-
@__prm2_0_rewritten='B\[%' (Size = 4000)
316+
@__prm2_0_startswith='B\[%' (Size = 4000)
317317
318318
SELECT [f].[Id], [f].[FirstName], [f].[LastName], [f].[NullableBool]
319319
FROM [FunkyCustomers] AS [f]
320-
WHERE [f].[FirstName] LIKE @__prm2_0_rewritten ESCAPE N'\'
320+
WHERE [f].[FirstName] LIKE @__prm2_0_startswith ESCAPE N'\'
321321
""",
322322
//
323323
"""
324-
@__prm3_0_rewritten='B\[\[a^%' (Size = 4000)
324+
@__prm3_0_startswith='B\[\[a^%' (Size = 4000)
325325
326326
SELECT [f].[Id], [f].[FirstName], [f].[LastName], [f].[NullableBool]
327327
FROM [FunkyCustomers] AS [f]
328-
WHERE [f].[FirstName] LIKE @__prm3_0_rewritten ESCAPE N'\'
328+
WHERE [f].[FirstName] LIKE @__prm3_0_startswith ESCAPE N'\'
329329
""",
330330
//
331331
"""
@@ -419,61 +419,61 @@ public override async Task String_ends_with_on_argument_with_wildcard_parameter(
419419
await base.String_ends_with_on_argument_with_wildcard_parameter(async);
420420

421421
AssertSql(
422-
"""
423-
@__prm1_0_rewritten='%\%r' (Size = 4000)
422+
"""
423+
@__prm1_0_endswith='%\%r' (Size = 4000)
424424
425425
SELECT [f].[FirstName]
426426
FROM [FunkyCustomers] AS [f]
427-
WHERE [f].[FirstName] LIKE @__prm1_0_rewritten ESCAPE N'\'
427+
WHERE [f].[FirstName] LIKE @__prm1_0_endswith ESCAPE N'\'
428428
""",
429-
//
430-
"""
431-
@__prm2_0_rewritten='%r\_' (Size = 4000)
429+
//
430+
"""
431+
@__prm2_0_endswith='%r\_' (Size = 4000)
432432
433433
SELECT [f].[FirstName]
434434
FROM [FunkyCustomers] AS [f]
435-
WHERE [f].[FirstName] LIKE @__prm2_0_rewritten ESCAPE N'\'
435+
WHERE [f].[FirstName] LIKE @__prm2_0_endswith ESCAPE N'\'
436436
""",
437-
//
438-
"""
437+
//
438+
"""
439439
SELECT [f].[FirstName]
440440
FROM [FunkyCustomers] AS [f]
441441
WHERE 0 = 1
442442
""",
443-
//
444-
"""
445-
@__prm4_0_rewritten='%' (Size = 4000)
443+
//
444+
"""
445+
@__prm4_0_endswith='%' (Size = 4000)
446446
447447
SELECT [f].[FirstName]
448448
FROM [FunkyCustomers] AS [f]
449-
WHERE [f].[FirstName] LIKE @__prm4_0_rewritten ESCAPE N'\'
449+
WHERE [f].[FirstName] LIKE @__prm4_0_endswith ESCAPE N'\'
450450
""",
451-
//
452-
"""
453-
@__prm5_0_rewritten='%\_r\_' (Size = 4000)
451+
//
452+
"""
453+
@__prm5_0_endswith='%\_r\_' (Size = 4000)
454454
455455
SELECT [f].[FirstName]
456456
FROM [FunkyCustomers] AS [f]
457-
WHERE [f].[FirstName] LIKE @__prm5_0_rewritten ESCAPE N'\'
457+
WHERE [f].[FirstName] LIKE @__prm5_0_endswith ESCAPE N'\'
458458
""",
459-
//
460-
"""
461-
@__prm6_0_rewritten='%a\%r\%' (Size = 4000)
459+
//
460+
"""
461+
@__prm6_0_endswith='%a\%r\%' (Size = 4000)
462462
463463
SELECT [f].[FirstName]
464464
FROM [FunkyCustomers] AS [f]
465-
WHERE [f].[FirstName] NOT LIKE @__prm6_0_rewritten ESCAPE N'\' OR [f].[FirstName] IS NULL
465+
WHERE [f].[FirstName] NOT LIKE @__prm6_0_endswith ESCAPE N'\' OR [f].[FirstName] IS NULL
466466
""",
467-
//
468-
"""
469-
@__prm7_0_rewritten='%' (Size = 4000)
467+
//
468+
"""
469+
@__prm7_0_endswith='%' (Size = 4000)
470470
471471
SELECT [f].[FirstName]
472472
FROM [FunkyCustomers] AS [f]
473-
WHERE [f].[FirstName] NOT LIKE @__prm7_0_rewritten ESCAPE N'\' OR [f].[FirstName] IS NULL
473+
WHERE [f].[FirstName] NOT LIKE @__prm7_0_endswith ESCAPE N'\' OR [f].[FirstName] IS NULL
474474
""",
475-
//
476-
"""
475+
//
476+
"""
477477
SELECT [f].[FirstName]
478478
FROM [FunkyCustomers] AS [f]
479479
""");
@@ -581,6 +581,21 @@ ORDER BY [f].[Id]
581581
""");
582582
}
583583

584+
public override async Task String_Contains_and_StartsWith_with_same_parameter(bool async)
585+
{
586+
await base.String_Contains_and_StartsWith_with_same_parameter(async);
587+
588+
AssertSql(
589+
"""
590+
@__s_0_contains='%B%' (Size = 4000)
591+
@__s_0_startswith='B%' (Size = 4000)
592+
593+
SELECT [f].[Id], [f].[FirstName], [f].[LastName], [f].[NullableBool]
594+
FROM [FunkyCustomers] AS [f]
595+
WHERE [f].[FirstName] LIKE @__s_0_contains ESCAPE N'\' OR [f].[LastName] LIKE @__s_0_startswith ESCAPE N'\'
596+
""");
597+
}
598+
584599
protected override void ClearLog()
585600
=> Fixture.TestSqlLoggerFactory.Clear();
586601

test/EFCore.SqlServer.FunctionalTests/Query/NorthwindFunctionsQuerySqlServerTest.cs

+6-6
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,11 @@ public override async Task String_StartsWith_Parameter(bool async)
9696

9797
AssertSql(
9898
"""
99-
@__pattern_0_rewritten='M%' (Size = 30)
99+
@__pattern_0_startswith='M%' (Size = 30)
100100
101101
SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region]
102102
FROM [Customers] AS [c]
103-
WHERE [c].[ContactName] LIKE @__pattern_0_rewritten ESCAPE N'\'
103+
WHERE [c].[ContactName] LIKE @__pattern_0_startswith ESCAPE N'\'
104104
""");
105105
}
106106

@@ -158,11 +158,11 @@ public override async Task String_EndsWith_Parameter(bool async)
158158

159159
AssertSql(
160160
"""
161-
@__pattern_0_rewritten='%b' (Size = 30)
161+
@__pattern_0_endswith='%b' (Size = 30)
162162
163163
SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region]
164164
FROM [Customers] AS [c]
165-
WHERE [c].[ContactName] LIKE @__pattern_0_rewritten ESCAPE N'\'
165+
WHERE [c].[ContactName] LIKE @__pattern_0_endswith ESCAPE N'\'
166166
""");
167167
}
168168

@@ -259,11 +259,11 @@ public override async Task String_Contains_parameter_with_whitespace(bool async)
259259

260260
AssertSql(
261261
"""
262-
@__pattern_0_rewritten='% %' (Size = 30)
262+
@__pattern_0_contains='% %' (Size = 30)
263263
264264
SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region]
265265
FROM [Customers] AS [c]
266-
WHERE [c].[ContactName] LIKE @__pattern_0_rewritten ESCAPE N'\'
266+
WHERE [c].[ContactName] LIKE @__pattern_0_contains ESCAPE N'\'
267267
""");
268268
}
269269

0 commit comments

Comments
 (0)