-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Query: Fix Set Operation design #17340
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM but take a look particularly at the comment regarding returning a shaper.
Definitely looks better than my previous implementation. I'd like us to not drop generating OrderBy/Skip/Take on naked set operations (instead of pushdown) - or at least the possibility of implementing in providers. But not critical if really not possible for 3.0.
test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs
Show resolved
Hide resolved
Also rest of team: @ajcvickers @divega @bricelam @AndriySvyryd @maumar While thinking about set operations and OrderBy/Skip/Take can appear directly after them, I came to conclusion that those 3 operations are exception rather than norm when it comes to set operations and pushdown. // Following is valid
Select 'a' AS [a]
Union
Select 'b' AS [a]
ORDER BY [a]
// Following needs pushdown
Select *
FROM (
Select 'a' AS [a]
Union
Select 'b' AS [a]
) as [t]
Join Orders as [o] on [t].[a] = [o].[MyProp]
So I arrived at conclusion that Set Operation should generate subquery right away when it is applied. In case if it is not composed over then it would be pulled up while printing to remove nesting. (we did similar for non-composed FromSql to support sproc). Now for OrderBy/Skip/Take not requiring pushdown is not black and white clear. It is true that you can generate 1 level of them. But if set operation is followed by series of skip/take/skip/take then you can apply first set of skip/take without pushdown but not the 2nd set. And then there is whole bunch of issues around ORDER BY printing in non-pushdown version. That is just rough idea. So should we add API surface on SetOperation to allow that in future or we can just add it later when we implement it. (Actual set operation types are concrete so it can be done in non-breaking way). As for "possibility of implementing in providers" - All providers support OrderBy/Skip/Take without pushdown. (Yes, SqlServer also does if you don't generate Top and use Fetch/Offset). I don't think there is any need to create a provider hook for this. It is low value and high cost to provide such hook to extend. |
Sounds good to me. We can use #16244 to track this.
Nice, that would translate Concat().Distinct() to Union().
The point is that Fetch/Offset require OrderBy, whereas TOP doesn't. So there is a little bit of SQL Server-specific complexity there. Note: this PR will also fix #16273, unless we want EF Core to also provide the extension methods expressing non-distinct Intersect/Except. If we don't providers can provide them instead. |
We inject OrderBy (Select 1) when needed already. I believe injecting |
Remove SetOperationType enum Add support for Intersect/Except Distinct Resolves #16709
b7d97f6
to
a383c4c
Compare
Last comment on #16273 talks about adding API on relational level on IQueryable. So leaving that issue open for future to add API, Infrastructure changes are already made. Perhaps, if you wish you can add API in postgre provider for now. |
Merging without additional surface on SetOperations for now. We can add it later in non-breaking way. |
Remove SetOperationType enum
Add support for Intersect/Except Distinct
Resolves #16709