Skip to content

Commit

Permalink
Propagate allowOptimizedExpansion to CASE results (#34304)
Browse files Browse the repository at this point in the history
* Propagate `allowOptimizedExpansion` to `CASE` results

If the `CASE` is used in a context that allows optimizations (predicates, where
NULL and FALSE are equivalent), the same holds for each of its results.
  • Loading branch information
ranma42 committed Jul 29, 2024
1 parent 1e0313e commit ac1b366
Show file tree
Hide file tree
Showing 8 changed files with 16 additions and 32 deletions.
4 changes: 2 additions & 2 deletions src/EFCore.Relational/Query/SqlNullabilityProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ protected virtual SqlExpression VisitCase(CaseExpression caseExpression, bool al
continue;
}

var newResult = Visit(whenClause.Result, out var resultNullable);
var newResult = Visit(whenClause.Result, allowOptimizedExpansion, out var resultNullable);

nullable |= resultNullable;
whenClauses.Add(new CaseWhenClause(test, newResult));
Expand All @@ -554,7 +554,7 @@ protected virtual SqlExpression VisitCase(CaseExpression caseExpression, bool al
SqlExpression? elseResult = null;
if (!testEvaluatesToTrue)
{
elseResult = Visit(caseExpression.ElseResult, out var elseResultNullable);
elseResult = Visit(caseExpression.ElseResult, allowOptimizedExpansion, out var elseResultNullable);
nullable |= elseResultNullable;

// if there is no 'else' there is a possibility of null, when none of the conditions are met
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -956,7 +956,7 @@ public override async Task Null_propagation_optimization2(bool async)
FROM [Gears] AS [g]
WHERE CASE
WHEN [g].[LeaderNickname] IS NULL THEN NULL
WHEN [g].[LeaderNickname] LIKE N'%us' AND [g].[LeaderNickname] IS NOT NULL THEN CAST(1 AS bit)
WHEN [g].[LeaderNickname] LIKE N'%us' THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END = CAST(1 AS bit)
""");
Expand Down Expand Up @@ -7708,10 +7708,7 @@ WHERE CASE
WHEN [g].[HasSoulPatch] = @__prm_0 AND (
SELECT TOP(1) [w].[Name]
FROM [Weapons] AS [w]
WHERE [w].[Id] = [g].[SquadId]) = @__prm2_1 AND (
SELECT TOP(1) [w].[Name]
FROM [Weapons] AS [w]
WHERE [w].[Id] = [g].[SquadId]) IS NOT NULL THEN CAST(1 AS bit)
WHERE [w].[Id] = [g].[SquadId]) = @__prm2_1 THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END = CAST(1 AS bit)
""");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2823,7 +2823,7 @@ ELSE CAST(0 AS bit)
END
ELSE [e].[BoolC]
END <> [e].[BoolB] THEN [e].[BoolA]
WHEN ([e].[NullableBoolB] = [e].[NullableBoolC] AND [e].[NullableBoolB] IS NOT NULL AND [e].[NullableBoolC] IS NOT NULL) OR ([e].[NullableBoolB] IS NULL AND [e].[NullableBoolC] IS NULL) THEN CAST(1 AS bit)
WHEN [e].[NullableBoolB] = [e].[NullableBoolC] OR ([e].[NullableBoolB] IS NULL AND [e].[NullableBoolC] IS NULL) THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END = CAST(1 AS bit)
""",
Expand Down Expand Up @@ -4342,7 +4342,7 @@ public override async Task Is_null_on_column_followed_by_OrElse_optimizes_nullab
FROM [Entities1] AS [e]
WHERE CASE
WHEN [e].[NullableStringA] IS NULL OR [e].[NullableStringB] IS NULL THEN CASE
WHEN ([e].[NullableStringA] = [e].[NullableStringB] AND [e].[NullableStringA] IS NOT NULL AND [e].[NullableStringB] IS NOT NULL) OR ([e].[NullableStringA] IS NULL AND [e].[NullableStringB] IS NULL) THEN CAST(1 AS bit)
WHEN [e].[NullableStringA] = [e].[NullableStringB] OR ([e].[NullableStringA] IS NULL AND [e].[NullableStringB] IS NULL) THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END
WHEN ([e].[NullableStringA] <> [e].[NullableStringB] OR [e].[NullableStringA] IS NULL OR [e].[NullableStringB] IS NULL) AND ([e].[NullableStringA] IS NOT NULL OR [e].[NullableStringB] IS NOT NULL) THEN CAST(1 AS bit)
Expand All @@ -4361,7 +4361,7 @@ public override async Task Is_null_on_column_followed_by_OrElse_optimizes_nullab
FROM [Entities1] AS [e]
WHERE CASE
WHEN ([e].[NullableStringA] IS NULL OR [e].[NullableStringB] IS NULL) AND [e].[NullableBoolC] IS NULL THEN CASE
WHEN ([e].[NullableStringA] = [e].[NullableStringB] AND [e].[NullableStringA] IS NOT NULL AND [e].[NullableStringB] IS NOT NULL) OR ([e].[NullableStringA] IS NULL AND [e].[NullableStringB] IS NULL) THEN CAST(1 AS bit)
WHEN [e].[NullableStringA] = [e].[NullableStringB] OR ([e].[NullableStringA] IS NULL AND [e].[NullableStringB] IS NULL) THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END
WHEN ([e].[NullableStringA] <> [e].[NullableStringB] OR [e].[NullableStringA] IS NULL OR [e].[NullableStringB] IS NULL) AND ([e].[NullableStringA] IS NOT NULL OR [e].[NullableStringB] IS NOT NULL) THEN CAST(1 AS bit)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1336,7 +1336,7 @@ FROM [Officers] AS [o]
) AS [u]
WHERE CASE
WHEN [u].[LeaderNickname] IS NULL THEN NULL
WHEN [u].[LeaderNickname] LIKE N'%us' AND [u].[LeaderNickname] IS NOT NULL THEN CAST(1 AS bit)
WHEN [u].[LeaderNickname] LIKE N'%us' THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END = CAST(1 AS bit)
""");
Expand Down Expand Up @@ -10264,10 +10264,7 @@ WHERE CASE
WHEN [u].[HasSoulPatch] = @__prm_0 AND (
SELECT TOP(1) [w].[Name]
FROM [Weapons] AS [w]
WHERE [w].[Id] = [u].[SquadId]) = @__prm2_1 AND (
SELECT TOP(1) [w].[Name]
FROM [Weapons] AS [w]
WHERE [w].[Id] = [u].[SquadId]) IS NOT NULL THEN CAST(1 AS bit)
WHERE [w].[Id] = [u].[SquadId]) = @__prm2_1 THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END = CAST(1 AS bit)
""");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1163,7 +1163,7 @@ FROM [Gears] AS [g]
LEFT JOIN [Officers] AS [o] ON [g].[Nickname] = [o].[Nickname] AND [g].[SquadId] = [o].[SquadId]
WHERE CASE
WHEN [g].[LeaderNickname] IS NULL THEN NULL
WHEN [g].[LeaderNickname] LIKE N'%us' AND [g].[LeaderNickname] IS NOT NULL THEN CAST(1 AS bit)
WHEN [g].[LeaderNickname] LIKE N'%us' THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END = CAST(1 AS bit)
""");
Expand Down Expand Up @@ -8724,10 +8724,7 @@ WHERE CASE
WHEN [g].[HasSoulPatch] = @__prm_0 AND (
SELECT TOP(1) [w].[Name]
FROM [Weapons] AS [w]
WHERE [w].[Id] = [g].[SquadId]) = @__prm2_1 AND (
SELECT TOP(1) [w].[Name]
FROM [Weapons] AS [w]
WHERE [w].[Id] = [g].[SquadId]) IS NOT NULL THEN CAST(1 AS bit)
WHERE [w].[Id] = [g].[SquadId]) = @__prm2_1 THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END = CAST(1 AS bit)
""");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1452,10 +1452,7 @@ WHERE CASE
WHEN [g].[HasSoulPatch] = @__prm_0 AND (
SELECT TOP(1) [w].[Name]
FROM [Weapons] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [w]
WHERE [w].[Id] = [g].[SquadId]) = @__prm2_1 AND (
SELECT TOP(1) [w].[Name]
FROM [Weapons] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [w]
WHERE [w].[Id] = [g].[SquadId]) IS NOT NULL THEN CAST(1 AS bit)
WHERE [w].[Id] = [g].[SquadId]) = @__prm2_1 THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END = CAST(1 AS bit)
""");
Expand Down Expand Up @@ -7768,7 +7765,7 @@ public override async Task Null_propagation_optimization2(bool async)
FROM [Gears] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [g]
WHERE CASE
WHEN [g].[LeaderNickname] IS NULL THEN NULL
WHEN [g].[LeaderNickname] LIKE N'%us' AND [g].[LeaderNickname] IS NOT NULL THEN CAST(1 AS bit)
WHEN [g].[LeaderNickname] LIKE N'%us' THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END = CAST(1 AS bit)
""");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3340,7 +3340,7 @@ public override async Task Null_propagation_optimization2(bool async)
FROM "Gears" AS "g"
WHERE CASE
WHEN "g"."LeaderNickname" IS NULL THEN NULL
ELSE "g"."LeaderNickname" LIKE '%us' AND "g"."LeaderNickname" IS NOT NULL
ELSE "g"."LeaderNickname" LIKE '%us'
END
""");
}
Expand Down Expand Up @@ -6766,11 +6766,7 @@ WHERE CASE
SELECT "w"."Name"
FROM "Weapons" AS "w"
WHERE "w"."Id" = "g"."SquadId"
LIMIT 1) = @__prm2_1 AND (
SELECT "w"."Name"
FROM "Weapons" AS "w"
WHERE "w"."Id" = "g"."SquadId"
LIMIT 1) IS NOT NULL
LIMIT 1) = @__prm2_1
ELSE 0
END
""");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -988,7 +988,7 @@ WHEN CASE
WHEN "e"."BoolA" THEN ("e"."NullableBoolA" <> "e"."NullableBoolB" OR "e"."NullableBoolA" IS NULL OR "e"."NullableBoolB" IS NULL) AND ("e"."NullableBoolA" IS NOT NULL OR "e"."NullableBoolB" IS NOT NULL)
ELSE "e"."BoolC"
END <> "e"."BoolB" THEN "e"."BoolA"
ELSE ("e"."NullableBoolB" = "e"."NullableBoolC" AND "e"."NullableBoolB" IS NOT NULL AND "e"."NullableBoolC" IS NOT NULL) OR ("e"."NullableBoolB" IS NULL AND "e"."NullableBoolC" IS NULL)
ELSE "e"."NullableBoolB" = "e"."NullableBoolC" OR ("e"."NullableBoolB" IS NULL AND "e"."NullableBoolC" IS NULL)
END
""",
//
Expand Down

0 comments on commit ac1b366

Please sign in to comment.