Conversation
| private readonly ISqlGenerationHelper _sqlGenerationHelper; | ||
| private readonly int _sqlServerCompatibilityLevel; | ||
|
|
||
| private bool _withinTable; |
There was a problem hiding this comment.
The changes for SQL Server generation are unfortunate and tricky...
SQL Server is very strict and does not allow a projection without an alias within a table subquery (SELECT ... FROM (SELECT 1 ...))); we already had special logic for generating 1 AS empty to work around this, but the logic for when to do this was incomplete. The pruning introduced in this PR caused selects within set operations to also possibly get their projection completely trimmed away, but our logic didn't catch that (this was an already-existing, possibly latent bug).
As a result, we need to do visitor state hacks to detect when the empty projection is directly in a subquery table, to generate AS empty only when needed.
| public override Task Update_non_main_table_in_entity_with_entity_splitting(bool async) | ||
| => Assert.ThrowsAnyAsync<Exception>( | ||
| () => base.Update_non_main_table_in_entity_with_entity_splitting(async)); | ||
| public override async Task Update_non_main_table_in_entity_with_entity_splitting(bool async) |
| WHERE ( | ||
| SELECT COUNT(*) | ||
| FROM [Animals] AS [a] | ||
| LEFT JOIN [Birds] AS [b] ON [a].[Id] = [b].[Id] |
There was a problem hiding this comment.
We weren't doing any pruning in subqueries that weren't table subqueries (this one is a scalar subquery inside the predicate).
| SELECT JSON_VALUE([o].[value], '$.OwnedReferenceLeaf.SomethingSomething') AS [c], [o].[key], CAST(JSON_VALUE([o].[value], '$.Date') AS datetime2) AS [c0] | ||
| FROM OPENJSON([j].[OwnedReferenceRoot], '$.OwnedCollectionBranch') AS [o] | ||
| ORDER BY CAST(JSON_VALUE([o].[value], '$.Date') AS datetime2) DESC | ||
| SELECT JSON_VALUE([o].[OwnedReferenceLeaf], '$.SomethingSomething') AS [c], [o].[Date] AS [c0] |
There was a problem hiding this comment.
This "expansion" from WITH-less OPENJSON to WITH-ful is actually an improvement; an upcoming PR will also prune unreferenced columns from the WITH column list.
| WHERE ( | ||
| SELECT COUNT(*) | ||
| FROM ( | ||
| SELECT [s].[value], [s].[key], CAST([s].[key] AS int) AS [c] |
There was a problem hiding this comment.
@maumar we discussed pruning these - so here we go :) I'm not sure any more if we opened an issue to track this (couldn't find one in a quick search)
| SELECT COUNT(*) | ||
| FROM ( | ||
| SELECT [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOfBirthName], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank], [t].[Discriminator], [t].[Nickname] AS [Name] | ||
| SELECT 1 AS empty |
There was a problem hiding this comment.
Nice example where having COUNT(*) at the top causes all projections inside to get pruned
Closes dotnet#31083 Fixes dotnet#31407
@ajcvickers you may be interested in taking a look, this is query stuff but relatively scoped to a specific problem etc.
Two additional pruning-related PRs also coming up based on this one.
Closes #31083
Fixes #31407