-
-
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
Add Postgres TABLESAMPLE support. #3921
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 working on this 👍 That's really helpful and the PR is a good starting point to iterate on.
Note the TODO comment regarding the AppearsInFromClause associated Count type. It is set to Once but I struggled to understand how this is used. If this means once per joinable fragment then it should be Once. However PostgreSQL does allow separate TABLESAMPLE clauses in each joinable fragment. Since it seems meant to pertain to the underlying table, perhaps it should be derived from the S type parameter? If so I'm afraid this is beyond my current understanding of the diesel_derives code :)
AppearsInFromClause::Count
there indicates how often a query source appears in your from clause. Once
says, that a certain query source (that one that's given to AppearsInFromClause
as generic argument) appears in your from clause, which later allows columns in select/filter/etc use that table. The added impl essentially just say that Tablesample
is samewhat transparent there and can be treated just like table
itself.
I'm not sure whether I've properly exported the TablesampleDsl trait correctly. In my application code, where I call .tablesample(...) I also need to use diesel::dsl::TablesampleDsl. That felt a little unexpected. I looked into re-exporting it into the prelude but I didn't see other backend-specific DSL traits re-exported there so I backed away.
The prelude reexports methods from expression_methods
: https://github.com/diesel-rs/diesel/blob/master/diesel/src/lib.rs#L648
which in turn reexports the backend specific variants: https://github.com/diesel-rs/diesel/blob/master/diesel/src/expression_methods/mod.rs. That written: That trait does not really fit into the expression_methods module as it's something different. I would likely reexport it directly from diesel::prelude
(and add OnlyDsl
as well there).
It seems most of the DSL tests are in the doctests. I tried to follow that pattern but I wasn't able to run those. A naive cargo rustdoc --features postgres -- --test led to all tests failing. I'd very much appreciate any direction you can provide to run those tests.
There are also some tests in diesel_tests
, but it should be fine use doc-tests for this functionality. After all we only care that it's covered somewhere.
For running the tests you need to:
- Set the
DATABASE_URL
environment variable to a database that should be used for tests - Run tests via
cargo test --no-default-features --features "postgres"
In addition to the doc tests, I would appreciate having at least one test for this in diesel_compile_tests
, that show this can only be used with the postgres backend.
Thank you for all of your feedback. I found it quite helpful! I have updated this branch to:
Regarding the type parameters, I'm hoping you can provide some feedback regarding how close my approach is to your suggestion. I don't use this approach much in my own code so I'm likely missing some of the nuance in the existing dsl code. The code works in my own project, however the second of the two doctests fails to compile and I'm struggling to figure out why. The error:
The difference between the two examples is the join, as the error indicates. However I'm having trouble understanding how the type constraints are being applied here. In
Since this impl targets
In
Since
It's pretty obvious that
So it seems my mistake is likely not satisfying this constraint:
However, with the exception of the TSM type parameter, this follows the |
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 the update. This is now much closer to what I had in mind 👍
I've left a bunch of comment for some changes to the exposed API, but the implementation itself, based on the generic marker types looks fine.
As for the errors with the joins: It looks like you might missing the equivalent of these impls:
diesel/diesel/src/macros/mod.rs
Lines 230 to 245 in 1c24bf6
impl $crate::query_source::TableNotEqual<$left::table> | |
for $crate::query_builder::Only<$right::table> | |
{ | |
} | |
impl $crate::query_source::TableNotEqual<$right::table> | |
for $crate::query_builder::Only<$left::table> | |
{ | |
} | |
impl $crate::query_source::TableNotEqual<$crate::query_builder::Only<$left::table>> | |
for $right::table | |
{ | |
} | |
impl $crate::query_source::TableNotEqual<$crate::query_builder::Only<$right::table>> | |
for $left::table | |
{ | |
} |
Also you likely need to update the output for the other compile tests as well as some of the error output is quite sensitive to what rustc emits (It contains a number of types that implement a certain trait, which obviously might change here)
diesel_compile_tests/tests/fail/pg_specific_tablesample_cannot_by_used_on_sqlite.stderr
Outdated
Show resolved
Hide resolved
diesel_compile_tests/tests/fail/pg_specific_tablesample_cannot_by_used_on_sqlite.rs
Outdated
Show resolved
Hide resolved
4ec897c
to
cc27cd9
Compare
Thanks for pointing me toward |
The fixes for the failing CI tests have been merged, so if you rebase your PR I can do a hopefully final review. |
cc27cd9
to
ef4af14
Compare
Thanks for the heads up. I've rebased this and marked it as ready for review. |
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 the update 👍
I'm sorry but I have another round of mostly minor comments about documentation and what to make public where. It would be great if you could address them, otherwise I might fix them myself in the next week.
The other thing that would be great to have is an entry into the Changelog.md
file mentioning this new feature.
From what I can tell reading through these on my phone they look like appropriate changes. I'd be happy to make them. I'll be away from my computer until the 1st of March though. |
No worries, take the time you need for this I would not have time to do this on my own in the next week or so. |
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 the update. It looks good now 👍
I will take care of the CI failure tomorrow. It seems to be unrelated (and caused by a new deprecation in a new chrono version)
These changes add support for queries like so:
The syntax, excerpt from the PostgreSQL docs:
I'm skeptical that these changes are ready to merge. The basic functionality does work for me in a side project. However I have not been able to test this to a level I feel comfortable with.
Note the TODO comment regarding the
AppearsInFromClause
associatedCount
type. It is set toOnce
but I struggled to understand how this is used. If this means once per joinable fragment then it should beOnce
. However PostgreSQL does allow separateTABLESAMPLE
clauses in each joinable fragment. Since it seems meant to pertain to the underlying table, perhaps it should be derived from theS
type parameter? If so I'm afraid this is beyond my current understanding of thediesel_derives
code :)I'm not sure whether I've properly exported the
TablesampleDsl
trait correctly. In my application code, where I call.tablesample(...)
I also need touse diesel::dsl::TablesampleDsl
. That felt a little unexpected. I looked into re-exporting it into the prelude but I didn't see other backend-specific DSL traits re-exported there so I backed away.It seems most of the DSL tests are in the doctests. I tried to follow that pattern but I wasn't able to run those. A naive
cargo rustdoc --features postgres -- --test
led to all tests failing. I'd very much appreciate any direction you can provide to run those tests.