sqlparser/dialect/mysql.rs
1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4//
5// http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12
13#[cfg(not(feature = "std"))]
14use alloc::boxed::Box;
15
16use crate::{
17 ast::{BinaryOperator, Expr},
18 dialect::Dialect,
19 keywords::Keyword,
20};
21
22/// A [`Dialect`] for [MySQL](https://www.mysql.com/)
23#[derive(Debug)]
24pub struct MySqlDialect {}
25
26impl Dialect for MySqlDialect {
27 fn is_identifier_start(&self, ch: char) -> bool {
28 // See https://dev.mysql.com/doc/refman/8.0/en/identifiers.html.
29 // Identifiers which begin with a digit are recognized while tokenizing numbers,
30 // so they can be distinguished from exponent numeric literals.
31 ch.is_alphabetic()
32 || ch == '_'
33 || ch == '$'
34 || ch == '@'
35 || ('\u{0080}'..='\u{ffff}').contains(&ch)
36 }
37
38 fn is_identifier_part(&self, ch: char) -> bool {
39 self.is_identifier_start(ch) || ch.is_ascii_digit()
40 }
41
42 fn is_delimited_identifier_start(&self, ch: char) -> bool {
43 ch == '`'
44 }
45
46 fn parse_infix(
47 &self,
48 parser: &mut crate::parser::Parser,
49 expr: &crate::ast::Expr,
50 _precedence: u8,
51 ) -> Option<Result<crate::ast::Expr, crate::parser::ParserError>> {
52 // Parse DIV as an operator
53 if parser.parse_keyword(Keyword::DIV) {
54 Some(Ok(Expr::BinaryOp {
55 left: Box::new(expr.clone()),
56 op: BinaryOperator::MyIntegerDivide,
57 right: Box::new(parser.parse_expr().unwrap()),
58 }))
59 } else {
60 None
61 }
62 }
63}