mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-25 16:34:04 +00:00
feat: Support MySQL's DIV
operator (#876)
* feat: MySQL's DIV operator * fix: do not use `_` prefix for used variable --------- Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org>
This commit is contained in:
parent
feaa13c9a9
commit
097e7ad56e
5 changed files with 38 additions and 1 deletions
|
@ -85,6 +85,8 @@ pub enum BinaryOperator {
|
||||||
BitwiseOr,
|
BitwiseOr,
|
||||||
BitwiseAnd,
|
BitwiseAnd,
|
||||||
BitwiseXor,
|
BitwiseXor,
|
||||||
|
/// MySQL [`DIV`](https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html) integer division
|
||||||
|
MyIntegerDivide,
|
||||||
/// Support for custom operators (built by parsers outside this crate)
|
/// Support for custom operators (built by parsers outside this crate)
|
||||||
Custom(String),
|
Custom(String),
|
||||||
PGBitwiseXor,
|
PGBitwiseXor,
|
||||||
|
@ -124,6 +126,7 @@ impl fmt::Display for BinaryOperator {
|
||||||
BinaryOperator::BitwiseOr => f.write_str("|"),
|
BinaryOperator::BitwiseOr => f.write_str("|"),
|
||||||
BinaryOperator::BitwiseAnd => f.write_str("&"),
|
BinaryOperator::BitwiseAnd => f.write_str("&"),
|
||||||
BinaryOperator::BitwiseXor => f.write_str("^"),
|
BinaryOperator::BitwiseXor => f.write_str("^"),
|
||||||
|
BinaryOperator::MyIntegerDivide => f.write_str("DIV"),
|
||||||
BinaryOperator::Custom(s) => f.write_str(s),
|
BinaryOperator::Custom(s) => f.write_str(s),
|
||||||
BinaryOperator::PGBitwiseXor => f.write_str("#"),
|
BinaryOperator::PGBitwiseXor => f.write_str("#"),
|
||||||
BinaryOperator::PGBitwiseShiftLeft => f.write_str("<<"),
|
BinaryOperator::PGBitwiseShiftLeft => f.write_str("<<"),
|
||||||
|
|
|
@ -10,7 +10,14 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use crate::dialect::Dialect;
|
#[cfg(not(feature = "std"))]
|
||||||
|
use alloc::boxed::Box;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
ast::{BinaryOperator, Expr},
|
||||||
|
dialect::Dialect,
|
||||||
|
keywords::Keyword,
|
||||||
|
};
|
||||||
|
|
||||||
/// [MySQL](https://www.mysql.com/)
|
/// [MySQL](https://www.mysql.com/)
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -35,4 +42,22 @@ impl Dialect for MySqlDialect {
|
||||||
fn is_delimited_identifier_start(&self, ch: char) -> bool {
|
fn is_delimited_identifier_start(&self, ch: char) -> bool {
|
||||||
ch == '`'
|
ch == '`'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_infix(
|
||||||
|
&self,
|
||||||
|
parser: &mut crate::parser::Parser,
|
||||||
|
expr: &crate::ast::Expr,
|
||||||
|
_precedence: u8,
|
||||||
|
) -> Option<Result<crate::ast::Expr, crate::parser::ParserError>> {
|
||||||
|
// Parse DIV as an operator
|
||||||
|
if parser.parse_keyword(Keyword::DIV) {
|
||||||
|
Some(Ok(Expr::BinaryOp {
|
||||||
|
left: Box::new(expr.clone()),
|
||||||
|
op: BinaryOperator::MyIntegerDivide,
|
||||||
|
right: Box::new(parser.parse_expr().unwrap()),
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -211,6 +211,7 @@ define_keywords!(
|
||||||
DISCONNECT,
|
DISCONNECT,
|
||||||
DISTINCT,
|
DISTINCT,
|
||||||
DISTRIBUTE,
|
DISTRIBUTE,
|
||||||
|
DIV,
|
||||||
DO,
|
DO,
|
||||||
DOUBLE,
|
DOUBLE,
|
||||||
DOW,
|
DOW,
|
||||||
|
|
|
@ -1982,6 +1982,8 @@ impl<'a> Parser<'a> {
|
||||||
const AND_PREC: u8 = 10;
|
const AND_PREC: u8 = 10;
|
||||||
const OR_PREC: u8 = 5;
|
const OR_PREC: u8 = 5;
|
||||||
|
|
||||||
|
const DIV_OP_PREC: u8 = 40;
|
||||||
|
|
||||||
/// Get the precedence of the next token
|
/// Get the precedence of the next token
|
||||||
pub fn get_next_precedence(&self) -> Result<u8, ParserError> {
|
pub fn get_next_precedence(&self) -> Result<u8, ParserError> {
|
||||||
// allow the dialect to override precedence logic
|
// allow the dialect to override precedence logic
|
||||||
|
@ -2031,6 +2033,7 @@ impl<'a> Parser<'a> {
|
||||||
Token::Word(w) if w.keyword == Keyword::ILIKE => Ok(Self::LIKE_PREC),
|
Token::Word(w) if w.keyword == Keyword::ILIKE => Ok(Self::LIKE_PREC),
|
||||||
Token::Word(w) if w.keyword == Keyword::SIMILAR => Ok(Self::LIKE_PREC),
|
Token::Word(w) if w.keyword == Keyword::SIMILAR => Ok(Self::LIKE_PREC),
|
||||||
Token::Word(w) if w.keyword == Keyword::OPERATOR => Ok(Self::BETWEEN_PREC),
|
Token::Word(w) if w.keyword == Keyword::OPERATOR => Ok(Self::BETWEEN_PREC),
|
||||||
|
Token::Word(w) if w.keyword == Keyword::DIV => Ok(Self::DIV_OP_PREC),
|
||||||
Token::Eq
|
Token::Eq
|
||||||
| Token::Lt
|
| Token::Lt
|
||||||
| Token::LtEq
|
| Token::LtEq
|
||||||
|
|
|
@ -1407,3 +1407,8 @@ fn parse_string_introducers() {
|
||||||
mysql().one_statement_parses_to("SELECT _utf8mb4'abc'", "SELECT _utf8mb4 'abc'");
|
mysql().one_statement_parses_to("SELECT _utf8mb4'abc'", "SELECT _utf8mb4 'abc'");
|
||||||
mysql().verified_stmt("SELECT _binary 'abc', _utf8mb4 'abc'");
|
mysql().verified_stmt("SELECT _binary 'abc', _utf8mb4 'abc'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_div_infix() {
|
||||||
|
mysql().verified_stmt(r#"SELECT 5 DIV 2"#);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue