-
-
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
implement MySQL Concat
Fragment; do not set PIPES_AS_CONCAT
by default
#3266
Conversation
…ery results in Vitess)
Note that I'm happy to make this configurable if you'd like me to—but sometimes more configuration options aren't worth the hassle. Your call 🚀 |
note a similar PR in sqlx: https://github.com/launchbadge/sqlx/pull/2037/files |
Thanks for opening this PR. Diesel sets this option explicitly to maintain compatibility with other database systems. It might be possible to achieve such compatibility by generating different SQL for the mysql backend. It's likely not as simple as just disabling an option in the connection setup, as shown by the failing tests. I would expect such a PR to pass the test suite. |
yep, I see that. Will work on getting the tests passing |
@weiznich I might need some assistance on this. I've identified this implementation of the concat query fragment here in impl<L, R, DB> QueryFragment<DB> for Concat<L, R>
where
L: QueryFragment<DB>,
R: QueryFragment<DB>,
DB: Backend,
{
fn walk_ast<'b>(
&'b self,
mut out: crate::query_builder::AstPass<'_, 'b, DB>,
) -> crate::result::QueryResult<()> {
// Those brackets are required because mysql is broken
// https://github.com/diesel-rs/diesel/issues/2133#issuecomment-517432317
out.push_sql("(");
self.left.walk_ast(out.reborrow())?;
out.push_sql(" || ");
self.right.walk_ast(out.reborrow())?;
out.push_sql(")");
Ok(())
}
} And I believe we need to do something like if mysql {
out.push_sql("CONCAT(");
self.left.walk_ast(out.reborrow())?;
out.push_sql(",");
self.right.walk_ast(out.reborrow())?;
out.push_sql(")");
return Ok(())
} ...but I'm not sure how to properly check the dialect on that first line. Can you offer guidance here? |
Such a conditional implementation needs to happen on type level. We have the Line 149 in 17c1bb4
#3257 introduces a such a type level flag for another usecase, so it can be use example of how to introduce such a type-level flag. This allows to just provide different wild card implementations of |
@weiznich I see that PR is Open—do I need to wait for it to be merged? |
like it would be something like this? #[diesel_derives::__diesel_public_if(
feature = "mysql"
)] ? |
Well, that didn't work. Can you tell me what I'm doing wrong here? |
This is not unexpected as this is just not the way I've suggested above 😉. Your implementation will fail as soon as some user enables more than on backend for diesel, which is to be clear a valid usecase. Follow the example given above and it should work. To answer the other questions quickly:
No you don't need for that to be merged. That's just an example case of how to introduce such a type level flag as required here. You need to do the "same" thing for
No you don't need that at all. This attribute macro toggles whether something is public or not depending on the passed cfg expression. This is not meaningful for the |
Got it, let me see if I can make those adjustments... |
Okay, @weiznich — am I at least heading in the right direction now? |
PIPES_AS_CONCAT
by default; implement MySQL Concat
Fragment
Okay, I think that's a yes 🙂 @weiznich can you help me get this over the finish line? I am having trouble running |
PIPES_AS_CONCAT
by default; implement MySQL Concat
FragmentConcat
Fragment; do not set PIPES_AS_CONCAT
by default
Yes that's the right approach, you've just asked that in the middle of my night.
This is likely caused by some minor change to an error message due to the changed internal implementations. You can fix that by just accepting and committing the changes via
|
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 updating the implementation. The actual code looks fine, but the documentation needs to be improved.
In addition to the two inline comments this also needs an changelog entry that mentions the removal of setting PIPES_AS_CONCAT
as concat operator on connection setup. This is a potentially breaking change for people that use ||
as concat in raw sql queries. We need to communicate this so that users can either adapt their code or manually enable that option on their own.
diesel/src/backend.rs
Outdated
/// `CONCAT` syntax to select a concatenation | ||
/// of two variables or string | ||
#[derive(Debug, Clone, Copy)] | ||
pub struct ConcatClause; |
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.
I would prefer a name here that indicates that any backend using this impl uses ||
as concat operator. Additionally the documentation should also mention this explicitly.
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.
✅
Vitess does not allow changing the parsing of MySQL queries themselves, and as such does not support the SQL modes "ANSI_QUOTES", "NO_BACKSLASH_ESCAPES", "PIPES_AS_CONCAT", and "REAL_AS_FLOAT"
https://github.com/vitessio/vitess/pull/10163/files#diff-9d2575386e98a47276e4d5c75e73cdefec7078a95ea4e159b50806a8c3099c1bR101
Vitess is a popular scalability layer on top of MySQL, used by default in PlanetScale, and we should support it by default (and either allow this mode to be added manually with config, or drop support for this mode)