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
27 changes: 25 additions & 2 deletions src/EFCore.Relational/Query/SqlNullabilityProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2032,7 +2032,30 @@ protected virtual SqlExpression OptimizeNonNullableNotExpression(SqlUnaryExpress
sqlBinaryOperand.TypeMapping)!;
}
}
break;
break;

case CaseExpression caseExpression:
{
if (caseExpression.Type == typeof(bool)
&& caseExpression.ElseResult is SqlConstantExpression elseResult
&& caseExpression.WhenClauses.All(clause => clause.Result is SqlConstantExpression)
)
{
var clauses = caseExpression.WhenClauses
.Select(clause => new CaseWhenClause(
clause.Test,
_sqlExpressionFactory.Constant(!(bool)(clause.Result as SqlConstantExpression)!.Value!, clause.Result.TypeMapping))
)
.ToList();
var newElseResult = _sqlExpressionFactory.Constant(!(bool)elseResult.Value!, elseResult.TypeMapping);

return caseExpression.Operand is null
? _sqlExpressionFactory.Case(clauses, newElseResult)
: _sqlExpressionFactory.Case(caseExpression.Operand, clauses, newElseResult);
}
}

break;
}

return sqlUnaryExpression;
Expand Down Expand Up @@ -2369,7 +2392,7 @@ private SqlExpression ProcessNullNotNull(SqlUnaryExpression sqlUnaryExpression,
return result;
}
}
break;
break;
}

return sqlUnaryExpression;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2100,6 +2100,20 @@ public override Task Where_ternary_boolean_condition_with_false_as_result_false(
SELECT c
FROM root c
WHERE ((c["Discriminator"] = "Product") AND false)
""");
});

public override Task Where_ternary_boolean_condition_negated(bool async)
=> Fixture.NoSyncTest(
async, async a =>
{
await base.Where_ternary_boolean_condition_negated(a);

AssertSql(
"""
SELECT c
FROM root c
WHERE ((c["Discriminator"] = "Product") AND NOT(((c["UnitsInStock"] >= 20) ? false : true)))
""");
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1465,6 +1465,15 @@ public virtual Task Where_ternary_boolean_condition_with_false_as_result_false(b
assertEmpty: true);
}

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Where_ternary_boolean_condition_negated(bool async)
{
return AssertQuery(
async,
ss => ss.Set<Product>().Where(p => !(p.UnitsInStock >= 20 ? false : true)));
}

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Where_compare_constructed_equal(bool async)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4127,9 +4127,9 @@ FROM [LevelTwo] AS [l0]
) AS [l1]
GROUP BY [l1].[Key]
) AS [l2] ON [l].[Id] = [l2].[Key] AND CASE
WHEN [l2].[Sum] <= 10 THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END = CAST(0 AS bit)
WHEN [l2].[Sum] <= 10 THEN CAST(0 AS bit)
ELSE CAST(1 AS bit)
END = CAST(1 AS bit)
""");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -975,9 +975,9 @@ WHERE [l2].[OneToOne_Required_PK_Date] IS NOT NULL AND [l2].[Level1_Required_Id]
) AS [s]
GROUP BY [s].[Key]
) AS [s1] ON [l].[Id] = [s1].[Key] AND CASE
WHEN [s1].[Sum] <= 10 THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END = CAST(0 AS bit)
WHEN [s1].[Sum] <= 10 THEN CAST(0 AS bit)
ELSE CAST(1 AS bit)
END = CAST(1 AS bit)
""");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1706,6 +1706,21 @@ FROM [Products] AS [p]
""");
}

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

AssertSql(
"""
SELECT [p].[ProductID], [p].[Discontinued], [p].[ProductName], [p].[SupplierID], [p].[UnitPrice], [p].[UnitsInStock]
FROM [Products] AS [p]
WHERE CASE
WHEN [p].[UnitsInStock] >= CAST(20 AS smallint) THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END = CAST(1 AS bit)
""");
}

public override async Task Where_compare_constructed_equal(bool async)
{
// Anonymous type to constant comparison. Issue #14672.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2543,9 +2543,9 @@ public override async Task Negated_order_comparison_on_nullable_arguments_doesnt
SELECT [e].[Id]
FROM [Entities1] AS [e]
WHERE CASE
WHEN [e].[NullableIntA] > @__i_0 THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END = CAST(0 AS bit)
WHEN [e].[NullableIntA] > @__i_0 THEN CAST(0 AS bit)
ELSE CAST(1 AS bit)
END = CAST(1 AS bit)
""",
//
"""
Expand All @@ -2554,9 +2554,9 @@ ELSE CAST(0 AS bit)
SELECT [e].[Id]
FROM [Entities1] AS [e]
WHERE CASE
WHEN [e].[NullableIntA] >= @__i_0 THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END = CAST(0 AS bit)
WHEN [e].[NullableIntA] >= @__i_0 THEN CAST(0 AS bit)
ELSE CAST(1 AS bit)
END = CAST(1 AS bit)
""",
//
"""
Expand All @@ -2565,9 +2565,9 @@ ELSE CAST(0 AS bit)
SELECT [e].[Id]
FROM [Entities1] AS [e]
WHERE CASE
WHEN [e].[NullableIntA] < @__i_0 THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END = CAST(0 AS bit)
WHEN [e].[NullableIntA] < @__i_0 THEN CAST(0 AS bit)
ELSE CAST(1 AS bit)
END = CAST(1 AS bit)
""",
//
"""
Expand All @@ -2576,9 +2576,9 @@ ELSE CAST(0 AS bit)
SELECT [e].[Id]
FROM [Entities1] AS [e]
WHERE CASE
WHEN [e].[NullableIntA] <= @__i_0 THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END = CAST(0 AS bit)
WHEN [e].[NullableIntA] <= @__i_0 THEN CAST(0 AS bit)
ELSE CAST(1 AS bit)
END = CAST(1 AS bit)
""");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -878,10 +878,10 @@ public override async Task String_Contains_negated_in_predicate(bool async)
"""
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 NOT (CASE
WHEN instr("c"."CompanyName", "c"."ContactName") > 0 THEN 1
ELSE 0
END)
WHERE CASE
WHEN instr("c"."CompanyName", "c"."ContactName") > 0 THEN 0
ELSE 1
END
""");
}

Expand All @@ -891,10 +891,10 @@ public override async Task String_Contains_negated_in_projection(bool async)

AssertSql(
"""
SELECT "c"."CustomerID" AS "Id", NOT (CASE
WHEN instr("c"."CompanyName", "c"."ContactName") > 0 THEN 1
ELSE 0
END) AS "Value"
SELECT "c"."CustomerID" AS "Id", CASE
WHEN instr("c"."CompanyName", "c"."ContactName") > 0 THEN 0
ELSE 1
END AS "Value"
FROM "Customers" AS "c"
""");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,21 @@ public NorthwindWhereQuerySqliteTest(NorthwindQuerySqliteFixture<NoopModelCustom
Fixture.TestSqlLoggerFactory.SetTestOutputHelper(testOutputHelper);
}

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

AssertSql(
"""
SELECT "p"."ProductID", "p"."Discontinued", "p"."ProductName", "p"."SupplierID", "p"."UnitPrice", "p"."UnitsInStock"
FROM "Products" AS "p"
WHERE CASE
WHEN "p"."UnitsInStock" >= 20 THEN 1
ELSE 0
END
""");
}

public override Task Where_datetimeoffset_now_component(bool async)
=> AssertTranslationFailed(() => base.Where_datetimeoffset_now_component(async));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -475,43 +475,43 @@ public override async Task Negated_order_comparison_on_nullable_arguments_doesnt

SELECT "e"."Id"
FROM "Entities1" AS "e"
WHERE NOT (CASE
WHEN "e"."NullableIntA" > @__i_0 THEN 1
ELSE 0
END)
WHERE CASE
WHEN "e"."NullableIntA" > @__i_0 THEN 0
ELSE 1
END
""",
//
"""
@__i_0='1' (Nullable = true)

SELECT "e"."Id"
FROM "Entities1" AS "e"
WHERE NOT (CASE
WHEN "e"."NullableIntA" >= @__i_0 THEN 1
ELSE 0
END)
WHERE CASE
WHEN "e"."NullableIntA" >= @__i_0 THEN 0
ELSE 1
END
""",
//
"""
@__i_0='1' (Nullable = true)

SELECT "e"."Id"
FROM "Entities1" AS "e"
WHERE NOT (CASE
WHEN "e"."NullableIntA" < @__i_0 THEN 1
ELSE 0
END)
WHERE CASE
WHEN "e"."NullableIntA" < @__i_0 THEN 0
ELSE 1
END
""",
//
"""
@__i_0='1' (Nullable = true)

SELECT "e"."Id"
FROM "Entities1" AS "e"
WHERE NOT (CASE
WHEN "e"."NullableIntA" <= @__i_0 THEN 1
ELSE 0
END)
WHERE CASE
WHEN "e"."NullableIntA" <= @__i_0 THEN 0
ELSE 1
END
""");
}

Expand Down