efcore: Query: Simplify case blocks in SQL tree
Currently we translate CompareTo naively, using case statements with 3 options, however those can be significantly optimized for cases where CompareTo itself is compared to 1, 0 -1
foo.CompareTo(bar) == 0 -> foo == bar
example test: Double_order_by_on_string_compare
example current sql:
SELECT [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId]
FROM [Weapons] AS [w]
ORDER BY CASE
WHEN (CASE
WHEN ([w].[Name] = N'Marcus'' Lancer') AND [w].[Name] IS NOT NULL THEN 0
WHEN [w].[Name] > N'Marcus'' Lancer' THEN 1
WHEN [w].[Name] < N'Marcus'' Lancer' THEN -1
END = 0) AND CASE
WHEN ([w].[Name] = N'Marcus'' Lancer') AND [w].[Name] IS NOT NULL THEN 0
WHEN [w].[Name] > N'Marcus'' Lancer' THEN 1
WHEN [w].[Name] < N'Marcus'' Lancer' THEN -1
END IS NOT NULL THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END, [w].[Id]
example improved sql:
SELECT [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId]
FROM [Weapons] AS [w]
ORDER BY CASE
WHEN [w].[Name] = N'Marcus'' Lancer'
THEN CAST(1 AS bit) ELSE CAST(0 AS bit)
END, [w].[Id]
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 2
- Comments: 21 (21 by maintainers)
Commits related to this issue
- Fix to #16092 - Query: Simplify case blocks in SQL tree Adding optimization to during post processing (null semantics) Trying to match CASE block that corresponds to CompareTo translation. If that ca... — committed to dotnet/efcore by maumar 4 years ago
- Fix to #16092 - Query: Simplify case blocks in SQL tree Adding optimization to during post processing (null semantics) Trying to match CASE block that corresponds to CompareTo translation. If that ca... — committed to dotnet/efcore by maumar 4 years ago
- Fix to #16092 - Query: Simplify case blocks in SQL tree Adding optimization to during post processing Trying to match CASE block that corresponds to CompareTo translation. If that case block is compa... — committed to dotnet/efcore by maumar 4 years ago
- Fix to #16092 - Query: Simplify case blocks in SQL tree Adding optimization to during post processing Trying to match CASE block that corresponds to CompareTo translation. If that case block is compa... — committed to dotnet/efcore by maumar 4 years ago
- Fix to #16092 - Query: Simplify case blocks in SQL tree Adding optimization to during post processing Trying to match CASE block that corresponds to CompareTo translation. If that case block is compa... — committed to dotnet/efcore by maumar 4 years ago
- Fix to #16092 - Query: Simplify case blocks in SQL tree Adding optimization to during post processing Trying to match CASE block that corresponds to CompareTo translation. If that case block is compa... — committed to dotnet/efcore by maumar 4 years ago
My main point here is that the simplification from
string.Compare(a, b) == 0
toa == b
(or if you prefer, for some reason,string.Equals(a,b)
) can/should be universal to all providers (relational or not), which is why I think it belongs in pre-processing and not in post-processing - why repeat that for each provider type.Re greater/less than, it seems odd to internally transform
string.Compare(a,b) > 0
toa > b
simply because that construct is never produced AFAIK in C# or VB. But if we want to do that, then like equality why not do this transformation in preprocessing (because again, it’s universal)?Maybe a quick call would help clear this up.