-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Multi column distinct_on
for Postgresql
#3628
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.
Thanks for opening this PR 👍
This looks fine for me (beside the minor thing about Self::Output
vs the dsl types)
Additionally I would like to see some compile test that verifies that we reject queries with multiple columns in .distinct_on
calls without matching order clause.
@weiznich, actually it failed with simple correct orders :( With simple orders (like |
I do not have a solution for that yet, so I need to find some time to search for a solution. I cannot promise that this happens this week due to other priorities. |
NP. I'm also working on this. First try, to generate all impl cases failed. Because it needs to generate a lot of code, like this:
if we have |
What you could try is something like that: trait OrderDecorator {
type Plain;
}
impl<C> OrderDecorator for C where C: Column {
type Plain = C;
}
impl<C> OrderDecorator for Desc<C> {
type Plain = C;
}
// implement it for `Asc` as well
impl<__D1,__D2, __O1, __O2> ValidOrderingForDistinct<DistinctOnClause<(__D1, __D2)>> for OrderClause<(__O1, __O2)>
where __O1: OrderDecorator<Plain = __D1>,
__O2: OrderDecorator<Plain = __D2>,
{}
// implement it for all other tuple sizes Note that I have not tested that, so there might be problems there. |
Wow, works! (I tested it for a tuple of two) |
There are just some patterns that keep coming up again and again in diesel. That's one of them. I should probably start writing more about those internals some day... |
That would be awesome! But... regarding the implementation, I found a tiny issue in your code. Here is the code for a tuple of two:
The issue is that it doesn't work for a query like this:
because One solution could be to have many impls per
|
Yes my implementation would only work with "matching" distinct and order by clauses. So the basic problem here is that the following combinations are fine:
So we need way more impls to describe that. For each tuple size n we need m impls where m is the maximal supported tuple size. (That ignores one or two additional impls to allow single column cases without tuples) That means it's just m*m impls. So for a max tuple size of 32 we have 1024 impl, for a max size of 128 we have 16k impls. That does not seem to scale well. I see the following options here:
I think variant 1 would make it hard to add support for the unsupported cases later on, because it might require removing these existing impls (which is a breaking change). Variant 2 would allow to add support for the unsupported cases, by just bumping the number. I personally would likely go with variant 2, although that will require some modifications to the |
But I'm not sure what exactly you suggested.
impl of the first one is harder :) |
I've meant to suggest this variant:
With the restriction that the max size of the distinct on and order by tuples is 5 (or whatever other limit). So really just a "few" (25) impls for all the cases, but for a low column count. I think that's the solution that should cover most of the use-cases and that's easy to communicate to the users. |
@weiznich I need your help. I pushed last changes.
To solve it, I tried to put
I'll try to find it, but I think you can lead me and review my changes in the meanwhile 🙏🏼 |
I will have a look at the macro later this week. As for the conflicting impls: You should be able to solve that with the |
There are still conflicts, after I put:
the conflicts are like before:
|
(This also uses a different strategy to generate these impls as that results in more maintainable code)
I've pushed a commit that hopefully should workaround these conflicting impls. It also restructures how these impls are generated so that the additional |
@weiznich thanks.
for this query:
|
solves the not implemented case. |
@weiznich I think there are no tests to check compile time errors, am I right? |
Tests to check for compile time error are usually placed here: https://github.com/diesel-rs/diesel/tree/master/diesel_compile_tests%2Ftests |
Thanks for finishing this up. I think it's now ready for being merged 🎉 |
It's NOT or it's NOW ready? :D |
It is supposed to be a "now" (I edit the post above as well) |
And... there is a problem. The old syntax doesn't work anymore.
with the following error:
Yet I'm not sure if it's related to this PR or not |
That's unfortunate :( It's very likely that this change: https://github.com/diesel-rs/diesel/pull/3628/files#diff-556fca1d890492102d32274fc8da5ebdf8759195ac66e9df5aec8ae849ea2c54R20 caused that issue. (In detail changing the restricting from |
@omid I think what I've written above is the actual issue. I've already tried to work on a fix and got something at works at least partially. See #3643 for that. It would be helpful if you can contribute test case that worked with diesel 2.0 and broke with 2.1 there. |
distinct_on
for PostgreSQL, like:.distinct_on((column_a, column_b))
. Main files related to this: