-
Notifications
You must be signed in to change notification settings - Fork 691
MySQL: Add support for SELECT modifiers
#2172
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
base: main
Are you sure you want to change the base?
Conversation
Adds support for MySQL-specific `SELECT` modifiers that appear after the
`SELECT` keyword. Grammar from the [docs]:
```sql
SELECT
[ALL | DISTINCT | DISTINCTROW ]
[HIGH_PRIORITY]
[STRAIGHT_JOIN]
[SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
[SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
select_expr [, select_expr] ...
```
Manual testing shows that these options can appear in any order relative
to each other, so for the sake of fidelity, we parse this separately
from how we parse distinct and other options for other dialects, in a
new `Parser::parse_select_modifiers` method.
`DISTINCTROW` is a legacy (but not deprecated) synonym for `DISTINCT`,
so it just gets canonicalized as `DISTINCT`.
[docs]: https://dev.mysql.com/doc/refman/8.4/en/select.html
460f829 to
a437a32
Compare
| fn parse_select_distinct_on() { | ||
| let sql = "SELECT DISTINCT ON (album_id) name FROM track ORDER BY album_id, milliseconds"; | ||
| let select = verified_only_select(sql); | ||
| let select = all_dialects_but_mysql().verified_only_select(sql); |
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.
| let select = all_dialects_but_mysql().verified_only_select(sql); | |
| let select = all_dialects_except(|d| d.is::<MySqlDialect>()).verified_only_select(sql); |
thinking instead of introducing a dedicated function we can reuse this helper?
| /// Parses SELECT modifiers and DISTINCT/ALL in any order. Allows HIGH_PRIORITY, STRAIGHT_JOIN, | ||
| /// SQL_SMALL_RESULT, SQL_BIG_RESULT, SQL_BUFFER_RESULT, SQL_NO_CACHE, SQL_CALC_FOUND_ROWS and | ||
| /// DISTINCT/DISTINCTROW/ALL to appear in any order. |
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.
| /// Parses SELECT modifiers and DISTINCT/ALL in any order. Allows HIGH_PRIORITY, STRAIGHT_JOIN, | |
| /// SQL_SMALL_RESULT, SQL_BIG_RESULT, SQL_BUFFER_RESULT, SQL_NO_CACHE, SQL_CALC_FOUND_ROWS and | |
| /// DISTINCT/DISTINCTROW/ALL to appear in any order. | |
| /// Parses `SELECT` modifiers and `DISTINCT/ALL` in any order. |
Thinking we can avoid enumerating the variants so that they don't go out of sync with the impl
| return parser_err!("Cannot specify both ALL and DISTINCT".to_string(), loc); | ||
| self.prev_token(); | ||
| return self.expected( | ||
| "ALL alone without DISTINCT or DISTINCTROW", |
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.
this diff seems incorrect to mention DISTINCTROW?
| let mut distinct: Option<Distinct> = None; | ||
| let mut has_all = false; |
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.
Can we instead introduce a proper enum to represent the three states? the current impl I think is harder to follow which combinations are valid and if/when the specified option is ignored in the output.
| } | ||
| distinct = Some(Distinct::Distinct); | ||
| } | ||
| Keyword::HIGH_PRIORITY => modifiers.high_priority = true, |
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.
| Keyword::HIGH_PRIORITY => modifiers.high_priority = true, | |
| Keyword::HIGH_PRIORITY if !modifiers.high_priority => modifiers.high_priority = true, |
similar for the others is something like this needed if it's invalid that they occur multiple times (can we add test cases for the behavior)?
| /// MySQL-specific SELECT modifiers. | ||
| /// | ||
| /// See [MySQL SELECT](https://dev.mysql.com/doc/refman/8.4/en/select.html). | ||
| pub select_modifiers: SelectModifiers, |
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.
| pub select_modifiers: SelectModifiers, | |
| pub select_modifiers: Option<SelectModifiers>, |
| #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] | ||
| #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] | ||
| pub struct SelectModifiers { | ||
| /// `HIGH_PRIORITY` gives the SELECT higher priority than statements that update a table. |
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.
could we include the mysql links individually on the fields as well? that way if other dialects add their own variants in the future the doc would be consistent
Adds support for MySQL-specific
SELECTmodifiers that appear after theSELECTkeyword. Grammar from the docs:Manual testing shows that these options can appear in any order relative to each other, so for the sake of fidelity, we parse this separately from how we parse distinct and other options for other dialects, in a new
Parser::parse_select_modifiersmethod.DISTINCTROWis a legacy (but not deprecated) synonym forDISTINCT, so it just gets canonicalized asDISTINCT.