Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/EFCore.Relational/Query/SqlNullabilityProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ public class SqlNullabilityProcessor
private readonly ISqlExpressionFactory _sqlExpressionFactory;
private bool _canCache;

private static readonly bool UseOldBehavior32208 =
AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue32208", out var enabled32208) && enabled32208;

/// <summary>
/// Creates a new instance of the <see cref="SqlNullabilityProcessor" /> class.
/// </summary>
Expand Down Expand Up @@ -650,6 +653,11 @@ protected virtual SqlExpression VisitIn(InExpression inExpression, bool allowOpt

var item = Visit(inExpression.Item, out var itemNullable);

if (!UseOldBehavior32208)
{
inExpression = inExpression.Update(item, inExpression.Subquery, inExpression.Values, inExpression.ValuesParameter);
}

if (inExpression.Subquery != null)
{
var subquery = Visit(inExpression.Subquery);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,20 @@ public virtual Task Project_primitive_collections_element(bool async)
},
assertOrder: true);

[ConditionalTheory] // #32208
[MemberData(nameof(IsAsyncData))]
public virtual Task Nested_contains_with_Lists_and_no_inferred_type_mapping(bool async)
{
var ints = new List<int> { 1, 2, 3 };
var strings = new List<string> { "one", "two", "three" };

// Note that in this query, the outer Contains really has no type mapping, neither for its source (collection parameter), nor
// for its item (the conditional expression returns constants). The default type mapping must be applied.
return AssertQuery(
async,
ss => ss.Set<PrimitiveCollectionsEntity>().Where(e => strings.Contains(ints.Contains(e.Int) ? "one" : "two")));
}

public abstract class PrimitiveCollectionsQueryFixtureBase : SharedStoreFixtureBase<PrimitiveCollectionsContext>, IQueryFixtureBase
{
private PrimitiveArrayData? _expectedData;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,21 @@ ORDER BY [p].[Id]
""");
}

public override async Task Nested_contains_with_Lists_and_no_inferred_type_mapping(bool async)
{
await base.Nested_contains_with_Lists_and_no_inferred_type_mapping(async);

AssertSql(
"""
SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE CASE
WHEN [p].[Int] IN (1, 2, 3) THEN N'one'
ELSE N'two'
END IN (N'one', N'two', N'three')
""");
}

[ConditionalFact]
public virtual void Check_all_tests_overridden()
=> TestHelpers.AssertAllMethodsOverridden(GetType());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1227,6 +1227,26 @@ ORDER BY [p].[Id]
""");
}

public override async Task Nested_contains_with_Lists_and_no_inferred_type_mapping(bool async)
{
await base.Nested_contains_with_Lists_and_no_inferred_type_mapping(async);

AssertSql(
"""
@__strings_0='["one","two","three"]' (Size = 4000)

SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE CASE
WHEN [p].[Int] IN (1, 2, 3) THEN N'one'
ELSE N'two'
END IN (
SELECT [s].[value]
FROM OPENJSON(@__strings_0) WITH ([value] nvarchar(max) '$') AS [s]
)
""");
}

[ConditionalFact]
public virtual void Check_all_tests_overridden()
=> TestHelpers.AssertAllMethodsOverridden(GetType());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ public override void Scalar_Function_with_nested_InExpression_translation()
SELECT [c].[Id], [c].[FirstName], [c].[LastName]
FROM [Customers] AS [c]
WHERE CASE
WHEN SUBSTRING([c].[FirstName], 0 + 1, 1) IN (N'A', N'B', N'C') THEN CAST(1 AS bit)
WHEN SUBSTRING([c].[FirstName], 0 + 1, 1) IN (N'A', N'B', N'C') AND SUBSTRING([c].[FirstName], 0 + 1, 1) IS NOT NULL THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END IN (CAST(1 AS bit), CAST(0 AS bit))
""");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1109,6 +1109,26 @@ public override async Task Project_empty_collection_of_nullables_and_collection_
(await Assert.ThrowsAsync<InvalidOperationException>(
() => base.Project_empty_collection_of_nullables_and_collection_only_containing_nulls(async))).Message);

public override async Task Nested_contains_with_Lists_and_no_inferred_type_mapping(bool async)
{
await base.Nested_contains_with_Lists_and_no_inferred_type_mapping(async);

AssertSql(
"""
@__strings_0='["one","two","three"]' (Size = 21)

SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE CASE
WHEN "p"."Int" IN (1, 2, 3) THEN 'one'
ELSE 'two'
END IN (
SELECT "s"."value"
FROM json_each(@__strings_0) AS "s"
)
""");
}

[ConditionalFact]
public virtual void Check_all_tests_overridden()
=> TestHelpers.AssertAllMethodsOverridden(GetType());
Expand Down