Skip to content

Commit ac1b366

Browse files
authored
Propagate allowOptimizedExpansion to CASE results (#34304)
* 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.
1 parent 1e0313e commit ac1b366

File tree

8 files changed

+16
-32
lines changed

8 files changed

+16
-32
lines changed

src/EFCore.Relational/Query/SqlNullabilityProcessor.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,7 @@ protected virtual SqlExpression VisitCase(CaseExpression caseExpression, bool al
531531
continue;
532532
}
533533

534-
var newResult = Visit(whenClause.Result, out var resultNullable);
534+
var newResult = Visit(whenClause.Result, allowOptimizedExpansion, out var resultNullable);
535535

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

560560
// if there is no 'else' there is a possibility of null, when none of the conditions are met

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

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -956,7 +956,7 @@ public override async Task Null_propagation_optimization2(bool async)
956956
FROM [Gears] AS [g]
957957
WHERE CASE
958958
WHEN [g].[LeaderNickname] IS NULL THEN NULL
959-
WHEN [g].[LeaderNickname] LIKE N'%us' AND [g].[LeaderNickname] IS NOT NULL THEN CAST(1 AS bit)
959+
WHEN [g].[LeaderNickname] LIKE N'%us' THEN CAST(1 AS bit)
960960
ELSE CAST(0 AS bit)
961961
END = CAST(1 AS bit)
962962
""");
@@ -7708,10 +7708,7 @@ WHERE CASE
77087708
WHEN [g].[HasSoulPatch] = @__prm_0 AND (
77097709
SELECT TOP(1) [w].[Name]
77107710
FROM [Weapons] AS [w]
7711-
WHERE [w].[Id] = [g].[SquadId]) = @__prm2_1 AND (
7712-
SELECT TOP(1) [w].[Name]
7713-
FROM [Weapons] AS [w]
7714-
WHERE [w].[Id] = [g].[SquadId]) IS NOT NULL THEN CAST(1 AS bit)
7711+
WHERE [w].[Id] = [g].[SquadId]) = @__prm2_1 THEN CAST(1 AS bit)
77157712
ELSE CAST(0 AS bit)
77167713
END = CAST(1 AS bit)
77177714
""");

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2823,7 +2823,7 @@ ELSE CAST(0 AS bit)
28232823
END
28242824
ELSE [e].[BoolC]
28252825
END <> [e].[BoolB] THEN [e].[BoolA]
2826-
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)
2826+
WHEN [e].[NullableBoolB] = [e].[NullableBoolC] OR ([e].[NullableBoolB] IS NULL AND [e].[NullableBoolC] IS NULL) THEN CAST(1 AS bit)
28272827
ELSE CAST(0 AS bit)
28282828
END = CAST(1 AS bit)
28292829
""",
@@ -4342,7 +4342,7 @@ public override async Task Is_null_on_column_followed_by_OrElse_optimizes_nullab
43424342
FROM [Entities1] AS [e]
43434343
WHERE CASE
43444344
WHEN [e].[NullableStringA] IS NULL OR [e].[NullableStringB] IS NULL THEN CASE
4345-
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)
4345+
WHEN [e].[NullableStringA] = [e].[NullableStringB] OR ([e].[NullableStringA] IS NULL AND [e].[NullableStringB] IS NULL) THEN CAST(1 AS bit)
43464346
ELSE CAST(0 AS bit)
43474347
END
43484348
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)
@@ -4361,7 +4361,7 @@ public override async Task Is_null_on_column_followed_by_OrElse_optimizes_nullab
43614361
FROM [Entities1] AS [e]
43624362
WHERE CASE
43634363
WHEN ([e].[NullableStringA] IS NULL OR [e].[NullableStringB] IS NULL) AND [e].[NullableBoolC] IS NULL THEN CASE
4364-
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)
4364+
WHEN [e].[NullableStringA] = [e].[NullableStringB] OR ([e].[NullableStringA] IS NULL AND [e].[NullableStringB] IS NULL) THEN CAST(1 AS bit)
43654365
ELSE CAST(0 AS bit)
43664366
END
43674367
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)

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

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1336,7 +1336,7 @@ FROM [Officers] AS [o]
13361336
) AS [u]
13371337
WHERE CASE
13381338
WHEN [u].[LeaderNickname] IS NULL THEN NULL
1339-
WHEN [u].[LeaderNickname] LIKE N'%us' AND [u].[LeaderNickname] IS NOT NULL THEN CAST(1 AS bit)
1339+
WHEN [u].[LeaderNickname] LIKE N'%us' THEN CAST(1 AS bit)
13401340
ELSE CAST(0 AS bit)
13411341
END = CAST(1 AS bit)
13421342
""");
@@ -10264,10 +10264,7 @@ WHERE CASE
1026410264
WHEN [u].[HasSoulPatch] = @__prm_0 AND (
1026510265
SELECT TOP(1) [w].[Name]
1026610266
FROM [Weapons] AS [w]
10267-
WHERE [w].[Id] = [u].[SquadId]) = @__prm2_1 AND (
10268-
SELECT TOP(1) [w].[Name]
10269-
FROM [Weapons] AS [w]
10270-
WHERE [w].[Id] = [u].[SquadId]) IS NOT NULL THEN CAST(1 AS bit)
10267+
WHERE [w].[Id] = [u].[SquadId]) = @__prm2_1 THEN CAST(1 AS bit)
1027110268
ELSE CAST(0 AS bit)
1027210269
END = CAST(1 AS bit)
1027310270
""");

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

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,7 +1163,7 @@ FROM [Gears] AS [g]
11631163
LEFT JOIN [Officers] AS [o] ON [g].[Nickname] = [o].[Nickname] AND [g].[SquadId] = [o].[SquadId]
11641164
WHERE CASE
11651165
WHEN [g].[LeaderNickname] IS NULL THEN NULL
1166-
WHEN [g].[LeaderNickname] LIKE N'%us' AND [g].[LeaderNickname] IS NOT NULL THEN CAST(1 AS bit)
1166+
WHEN [g].[LeaderNickname] LIKE N'%us' THEN CAST(1 AS bit)
11671167
ELSE CAST(0 AS bit)
11681168
END = CAST(1 AS bit)
11691169
""");
@@ -8724,10 +8724,7 @@ WHERE CASE
87248724
WHEN [g].[HasSoulPatch] = @__prm_0 AND (
87258725
SELECT TOP(1) [w].[Name]
87268726
FROM [Weapons] AS [w]
8727-
WHERE [w].[Id] = [g].[SquadId]) = @__prm2_1 AND (
8728-
SELECT TOP(1) [w].[Name]
8729-
FROM [Weapons] AS [w]
8730-
WHERE [w].[Id] = [g].[SquadId]) IS NOT NULL THEN CAST(1 AS bit)
8727+
WHERE [w].[Id] = [g].[SquadId]) = @__prm2_1 THEN CAST(1 AS bit)
87318728
ELSE CAST(0 AS bit)
87328729
END = CAST(1 AS bit)
87338730
""");

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

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1452,10 +1452,7 @@ WHERE CASE
14521452
WHEN [g].[HasSoulPatch] = @__prm_0 AND (
14531453
SELECT TOP(1) [w].[Name]
14541454
FROM [Weapons] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [w]
1455-
WHERE [w].[Id] = [g].[SquadId]) = @__prm2_1 AND (
1456-
SELECT TOP(1) [w].[Name]
1457-
FROM [Weapons] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [w]
1458-
WHERE [w].[Id] = [g].[SquadId]) IS NOT NULL THEN CAST(1 AS bit)
1455+
WHERE [w].[Id] = [g].[SquadId]) = @__prm2_1 THEN CAST(1 AS bit)
14591456
ELSE CAST(0 AS bit)
14601457
END = CAST(1 AS bit)
14611458
""");
@@ -7768,7 +7765,7 @@ public override async Task Null_propagation_optimization2(bool async)
77687765
FROM [Gears] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [g]
77697766
WHERE CASE
77707767
WHEN [g].[LeaderNickname] IS NULL THEN NULL
7771-
WHEN [g].[LeaderNickname] LIKE N'%us' AND [g].[LeaderNickname] IS NOT NULL THEN CAST(1 AS bit)
7768+
WHEN [g].[LeaderNickname] LIKE N'%us' THEN CAST(1 AS bit)
77727769
ELSE CAST(0 AS bit)
77737770
END = CAST(1 AS bit)
77747771
""");

test/EFCore.Sqlite.FunctionalTests/Query/GearsOfWarQuerySqliteTest.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3340,7 +3340,7 @@ public override async Task Null_propagation_optimization2(bool async)
33403340
FROM "Gears" AS "g"
33413341
WHERE CASE
33423342
WHEN "g"."LeaderNickname" IS NULL THEN NULL
3343-
ELSE "g"."LeaderNickname" LIKE '%us' AND "g"."LeaderNickname" IS NOT NULL
3343+
ELSE "g"."LeaderNickname" LIKE '%us'
33443344
END
33453345
""");
33463346
}
@@ -6766,11 +6766,7 @@ WHERE CASE
67666766
SELECT "w"."Name"
67676767
FROM "Weapons" AS "w"
67686768
WHERE "w"."Id" = "g"."SquadId"
6769-
LIMIT 1) = @__prm2_1 AND (
6770-
SELECT "w"."Name"
6771-
FROM "Weapons" AS "w"
6772-
WHERE "w"."Id" = "g"."SquadId"
6773-
LIMIT 1) IS NOT NULL
6769+
LIMIT 1) = @__prm2_1
67746770
ELSE 0
67756771
END
67766772
""");

test/EFCore.Sqlite.FunctionalTests/Query/NullSemanticsQuerySqliteTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -988,7 +988,7 @@ WHEN CASE
988988
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)
989989
ELSE "e"."BoolC"
990990
END <> "e"."BoolB" THEN "e"."BoolA"
991-
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)
991+
ELSE "e"."NullableBoolB" = "e"."NullableBoolC" OR ("e"."NullableBoolB" IS NULL AND "e"."NullableBoolC" IS NULL)
992992
END
993993
""",
994994
//

0 commit comments

Comments
 (0)