Skip to content

Commit e4ce893

Browse files
committed
Fix OPENJSON column name when going over 2100 params
Fixes #37569
1 parent 10ac4da commit e4ce893

File tree

2 files changed

+49
-15
lines changed

2 files changed

+49
-15
lines changed

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

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ public class SqlServerSqlNullabilityProcessor : SqlNullabilityProcessor
4141
private int _openJsonAliasCounter;
4242
private int _totalParameterCount;
4343

44+
private static readonly bool UseOldBehavior37569 =
45+
AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue37569", out var enabled37569) && enabled37569;
46+
4447
/// <summary>
4548
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
4649
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
@@ -270,6 +273,10 @@ protected override SqlExpression VisitIn(InExpression inExpression, bool allowOp
270273
out var constants,
271274
out var containsNulls))
272275
{
276+
var columnName = UseOldBehavior37569
277+
? "value"
278+
: RelationalQueryableMethodTranslatingExpressionVisitor.ValuesValueColumnName;
279+
273280
inExpression = (openJson, constants) switch
274281
{
275282
(not null, null)
@@ -281,12 +288,12 @@ protected override SqlExpression VisitIn(InExpression inExpression, bool allowOp
281288
[
282289
new ProjectionExpression(
283290
new ColumnExpression(
284-
"value",
291+
columnName,
285292
openJson.Alias,
286293
valuesParameter.Type.GetSequenceType(),
287294
elementTypeMapping,
288295
containsNulls!.Value),
289-
"value")
296+
columnName)
290297
],
291298
null!)),
292299

@@ -344,7 +351,9 @@ private bool TryHandleOverLimitParameters(
344351
[
345352
new SqlServerOpenJsonExpression.ColumnInfo
346353
{
347-
Name = "value",
354+
Name = UseOldBehavior37569
355+
? "value"
356+
: RelationalQueryableMethodTranslatingExpressionVisitor.ValuesValueColumnName,
348357
TypeMapping = typeMapping,
349358
Path = [],
350359
}

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

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -99,14 +99,22 @@ public override async Task Parameter_collection_Count_with_huge_number_of_values
9999
{
100100
await base.Parameter_collection_Count_with_huge_number_of_values();
101101

102-
Assert.Contains("OPENJSON(@ids) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
102+
Assert.EndsWith(
103+
"""
104+
WHERE (
105+
SELECT COUNT(*)
106+
FROM OPENJSON(@ids) WITH ([Value] int '$') AS [i]
107+
WHERE [i].[Value] > [p].[Id]) > 0
108+
""".ReplaceLineEndings(),
109+
Fixture.TestSqlLoggerFactory.SqlStatements[0].ReplaceLineEndings(),
110+
StringComparison.Ordinal);
103111
}
104112

105113
public override async Task Parameter_collection_Count_with_huge_number_of_values_over_5_operations()
106114
{
107115
await base.Parameter_collection_Count_with_huge_number_of_values_over_5_operations();
108116

109-
Assert.Contains("OPENJSON(@ids) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
117+
Assert.Contains("OPENJSON(@ids) WITH ([Value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
110118
}
111119

112120
public override async Task Parameter_collection_Count_with_huge_number_of_values_over_5_operations_same_parameter()
@@ -121,7 +129,7 @@ public override async Task Parameter_collection_Count_with_huge_number_of_values
121129
{
122130
await base.Parameter_collection_Count_with_huge_number_of_values_over_2_operations_same_parameter_different_type_mapping();
123131

124-
Assert.Contains("OPENJSON(@ids) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
132+
Assert.Contains("OPENJSON(@ids) WITH ([Value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
125133
}
126134

127135
public override async Task Parameter_collection_Count_with_huge_number_of_values_over_5_operations_forced_constants()
@@ -136,23 +144,40 @@ public override async Task Parameter_collection_Count_with_huge_number_of_values
136144
{
137145
await base.Parameter_collection_Count_with_huge_number_of_values_over_5_operations_mixed_parameters_constants();
138146

139-
Assert.Contains("OPENJSON(@ids) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
147+
Assert.Contains("OPENJSON(@ids) WITH ([Value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
140148
}
141149

142150
public override async Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values()
143151
{
144152
await base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values();
145153

146-
Assert.Contains("OPENJSON(@ints) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
147-
Assert.Contains("OPENJSON(@ints) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
154+
Assert.EndsWith(
155+
"""
156+
WHERE [p].[Int] IN (
157+
SELECT [__openjson0].[Value]
158+
FROM OPENJSON(@ints) WITH ([Value] int '$') AS [__openjson0]
159+
)
160+
""".ReplaceLineEndings(),
161+
Fixture.TestSqlLoggerFactory.SqlStatements[0].ReplaceLineEndings(),
162+
StringComparison.Ordinal);
163+
164+
Assert.EndsWith(
165+
"""
166+
WHERE [p].[Int] NOT IN (
167+
SELECT [__openjson0].[Value]
168+
FROM OPENJSON(@ints) WITH ([Value] int '$') AS [__openjson0]
169+
)
170+
""".ReplaceLineEndings(),
171+
Fixture.TestSqlLoggerFactory.SqlStatements[1].ReplaceLineEndings(),
172+
StringComparison.Ordinal);
148173
}
149174

150175
public override async Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations()
151176
{
152177
await base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations();
153178

154-
Assert.Contains("OPENJSON(@ints) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
155-
Assert.Contains("OPENJSON(@ints) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
179+
Assert.Contains("OPENJSON(@ints) WITH ([Value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
180+
Assert.Contains("OPENJSON(@ints) WITH ([Value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
156181
}
157182

158183
public override async Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_same_parameter()
@@ -169,8 +194,8 @@ public override async Task Parameter_collection_of_ints_Contains_int_with_huge_n
169194
{
170195
await base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_2_operations_same_parameter_different_type_mapping();
171196

172-
Assert.Contains("OPENJSON(@ints) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
173-
Assert.Contains("OPENJSON(@ints) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
197+
Assert.Contains("OPENJSON(@ints) WITH ([Value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
198+
Assert.Contains("OPENJSON(@ints) WITH ([Value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
174199
}
175200

176201
public override async Task Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_forced_constants()
@@ -187,8 +212,8 @@ public override async Task Parameter_collection_of_ints_Contains_int_with_huge_n
187212
{
188213
await base.Parameter_collection_of_ints_Contains_int_with_huge_number_of_values_over_5_operations_mixed_parameters_constants();
189214

190-
Assert.Contains("OPENJSON(@ints) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
191-
Assert.Contains("OPENJSON(@ints) WITH ([value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
215+
Assert.Contains("OPENJSON(@ints) WITH ([Value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[0], StringComparison.Ordinal);
216+
Assert.Contains("OPENJSON(@ints) WITH ([Value] int '$')", Fixture.TestSqlLoggerFactory.SqlStatements[1], StringComparison.Ordinal);
192217
}
193218

194219
public override async Task Inline_collection_of_ints_Contains()

0 commit comments

Comments
 (0)