Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion src/dialect/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,9 @@ pub use self::teradata::TeradataDialect;
#[cfg(feature = "derive-dialect")]
pub use sqlparser_derive::derive_dialect;

use crate::ast::{ColumnOption, DataType, Expr, GranteesType, Ident, ObjectNamePart, Statement};
use crate::ast::{
BinaryOperator, ColumnOption, DataType, Expr, GranteesType, Ident, ObjectNamePart, Statement,
};
pub use crate::keywords;
use crate::keywords::Keyword;
use crate::parser::{Parser, ParserError};
Expand Down Expand Up @@ -2295,6 +2297,26 @@ pub fn dialect_from_str(dialect_name: impl AsRef<str>) -> Option<Box<dyn Dialect
}
}

/// Parse `DIV` using the caller's infix precedence.
fn parse_div_infix(
parser: &mut Parser,
expr: &Expr,
precedence: u8,
) -> Option<Result<Expr, ParserError>> {
if !parser.parse_keyword(Keyword::DIV) {
return None;
}
Some(
parser
.parse_subexpr(precedence)
.map(|right| Expr::BinaryOp {
left: Box::new(expr.clone()),
op: BinaryOperator::MyIntegerDivide,
right: Box::new(right),
}),
)
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
27 changes: 5 additions & 22 deletions src/dialect/mysql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,8 @@
// specific language governing permissions and limitations
// under the License.

#[cfg(not(feature = "std"))]
use alloc::boxed::Box;

use crate::{
ast::{BinaryOperator, Expr, LockTable, LockTableType, Statement},
ast::{Expr, LockTable, LockTableType, Statement},
dialect::{BindPlaceholderStyle, Dialect, Precedence},
keywords::Keyword,
parser::{Parser, ParserError},
Expand Down Expand Up @@ -115,25 +112,11 @@ impl Dialect for MySqlDialect {

fn parse_infix(
&self,
parser: &mut crate::parser::Parser,
expr: &crate::ast::Expr,
parser: &mut Parser,
expr: &Expr,
precedence: u8,
) -> Option<Result<crate::ast::Expr, ParserError>> {
// Parse DIV as an operator
if parser.parse_keyword(Keyword::DIV) {
let left = Box::new(expr.clone());
let right = Box::new(match parser.parse_subexpr(precedence) {
Ok(expr) => expr,
Err(e) => return Some(Err(e)),
});
Some(Ok(Expr::BinaryOp {
left,
op: BinaryOperator::MyIntegerDivide,
right,
}))
} else {
None
}
) -> Option<Result<Expr, ParserError>> {
super::parse_div_infix(parser, expr, precedence)
}

fn parse_statement(&self, parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
Expand Down
21 changes: 2 additions & 19 deletions src/dialect/spark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,8 @@
// specific language governing permissions and limitations
// under the License.

#[cfg(not(feature = "std"))]
use alloc::boxed::Box;

use crate::ast::{BinaryOperator, Expr};
use crate::ast::Expr;
use crate::dialect::Dialect;
use crate::keywords::Keyword;
use crate::parser::{Parser, ParserError};

/// A [`Dialect`] for [Apache Spark SQL](https://spark.apache.org/docs/latest/sql-ref.html).
Expand Down Expand Up @@ -155,19 +151,6 @@ impl Dialect for SparkSqlDialect {
expr: &Expr,
precedence: u8,
) -> Option<Result<Expr, ParserError>> {
if parser.parse_keyword(Keyword::DIV) {
let left = Box::new(expr.clone());
let right = Box::new(match parser.parse_subexpr(precedence) {
Ok(expr) => expr,
Err(e) => return Some(Err(e)),
});
Some(Ok(Expr::BinaryOp {
left,
op: BinaryOperator::MyIntegerDivide,
right,
}))
} else {
None
}
super::parse_div_infix(parser, expr, precedence)
}
}
20 changes: 20 additions & 0 deletions tests/sqlparser_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22210,3 +22210,23 @@ fn parse_reference_clauses_leave_duplicates_unconsumed() {
}
}
}

#[test]
fn parse_div_with_nested_divisor() {
let dialects = TestedDialects::new(vec![
Box::new(MySqlDialect {}),
Box::new(sqlparser::dialect::SparkSqlDialect),
]);
assert_eq!(
dialects.verified_expr("10 DIV (5 DIV 2)"),
Expr::BinaryOp {
left: Box::new(Expr::value(number("10"))),
op: BinaryOperator::MyIntegerDivide,
right: Box::new(Expr::Nested(Box::new(Expr::BinaryOp {
left: Box::new(Expr::value(number("5"))),
op: BinaryOperator::MyIntegerDivide,
right: Box::new(Expr::value(number("2"))),
}))),
}
);
}
Loading