mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-17 20:50:16 +00:00
Add logical xor (#357)
This commit is contained in:
parent
a8901becc3
commit
014b82f03d
5 changed files with 83 additions and 0 deletions
|
@ -71,6 +71,7 @@ pub enum BinaryOperator {
|
||||||
NotEq,
|
NotEq,
|
||||||
And,
|
And,
|
||||||
Or,
|
Or,
|
||||||
|
Xor,
|
||||||
Like,
|
Like,
|
||||||
NotLike,
|
NotLike,
|
||||||
ILike,
|
ILike,
|
||||||
|
@ -105,6 +106,7 @@ impl fmt::Display for BinaryOperator {
|
||||||
BinaryOperator::NotEq => "<>",
|
BinaryOperator::NotEq => "<>",
|
||||||
BinaryOperator::And => "AND",
|
BinaryOperator::And => "AND",
|
||||||
BinaryOperator::Or => "OR",
|
BinaryOperator::Or => "OR",
|
||||||
|
BinaryOperator::Xor => "XOR",
|
||||||
BinaryOperator::Like => "LIKE",
|
BinaryOperator::Like => "LIKE",
|
||||||
BinaryOperator::NotLike => "NOT LIKE",
|
BinaryOperator::NotLike => "NOT LIKE",
|
||||||
BinaryOperator::ILike => "ILIKE",
|
BinaryOperator::ILike => "ILIKE",
|
||||||
|
|
|
@ -494,6 +494,7 @@ define_keywords!(
|
||||||
WITHOUT,
|
WITHOUT,
|
||||||
WORK,
|
WORK,
|
||||||
WRITE,
|
WRITE,
|
||||||
|
XOR,
|
||||||
YEAR,
|
YEAR,
|
||||||
ZONE
|
ZONE
|
||||||
);
|
);
|
||||||
|
|
|
@ -898,6 +898,7 @@ impl<'a> Parser<'a> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Keyword::XOR => Some(BinaryOperator::Xor),
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -1018,6 +1019,7 @@ impl<'a> Parser<'a> {
|
||||||
match token {
|
match token {
|
||||||
Token::Word(w) if w.keyword == Keyword::OR => Ok(5),
|
Token::Word(w) if w.keyword == Keyword::OR => Ok(5),
|
||||||
Token::Word(w) if w.keyword == Keyword::AND => Ok(10),
|
Token::Word(w) if w.keyword == Keyword::AND => Ok(10),
|
||||||
|
Token::Word(w) if w.keyword == Keyword::XOR => Ok(24),
|
||||||
Token::Word(w) if w.keyword == Keyword::NOT => match self.peek_nth_token(1) {
|
Token::Word(w) if w.keyword == Keyword::NOT => match self.peek_nth_token(1) {
|
||||||
// The precedence of NOT varies depending on keyword that
|
// The precedence of NOT varies depending on keyword that
|
||||||
// follows it. If it is followed by IN, BETWEEN, or LIKE,
|
// follows it. If it is followed by IN, BETWEEN, or LIKE,
|
||||||
|
|
|
@ -824,7 +824,47 @@ mod tests {
|
||||||
Token::Whitespace(Whitespace::Space),
|
Token::Whitespace(Whitespace::Space),
|
||||||
Token::make_word("three", None),
|
Token::make_word("three", None),
|
||||||
];
|
];
|
||||||
|
compare(expected, tokens);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn tokenize_logical_xor() {
|
||||||
|
let sql =
|
||||||
|
String::from("SELECT true XOR true, false XOR false, true XOR false, false XOR true");
|
||||||
|
let dialect = GenericDialect {};
|
||||||
|
let mut tokenizer = Tokenizer::new(&dialect, &sql);
|
||||||
|
let tokens = tokenizer.tokenize().unwrap();
|
||||||
|
|
||||||
|
let expected = vec![
|
||||||
|
Token::make_keyword("SELECT"),
|
||||||
|
Token::Whitespace(Whitespace::Space),
|
||||||
|
Token::make_keyword("true"),
|
||||||
|
Token::Whitespace(Whitespace::Space),
|
||||||
|
Token::make_keyword("XOR"),
|
||||||
|
Token::Whitespace(Whitespace::Space),
|
||||||
|
Token::make_keyword("true"),
|
||||||
|
Token::Comma,
|
||||||
|
Token::Whitespace(Whitespace::Space),
|
||||||
|
Token::make_keyword("false"),
|
||||||
|
Token::Whitespace(Whitespace::Space),
|
||||||
|
Token::make_keyword("XOR"),
|
||||||
|
Token::Whitespace(Whitespace::Space),
|
||||||
|
Token::make_keyword("false"),
|
||||||
|
Token::Comma,
|
||||||
|
Token::Whitespace(Whitespace::Space),
|
||||||
|
Token::make_keyword("true"),
|
||||||
|
Token::Whitespace(Whitespace::Space),
|
||||||
|
Token::make_keyword("XOR"),
|
||||||
|
Token::Whitespace(Whitespace::Space),
|
||||||
|
Token::make_keyword("false"),
|
||||||
|
Token::Comma,
|
||||||
|
Token::Whitespace(Whitespace::Space),
|
||||||
|
Token::make_keyword("false"),
|
||||||
|
Token::Whitespace(Whitespace::Space),
|
||||||
|
Token::make_keyword("XOR"),
|
||||||
|
Token::Whitespace(Whitespace::Space),
|
||||||
|
Token::make_keyword("true"),
|
||||||
|
];
|
||||||
compare(expected, tokens);
|
compare(expected, tokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -815,6 +815,44 @@ fn parse_bitwise_ops() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_logical_xor() {
|
||||||
|
let sql = "SELECT true XOR true, false XOR false, true XOR false, false XOR true";
|
||||||
|
let select = verified_only_select(sql);
|
||||||
|
assert_eq!(
|
||||||
|
SelectItem::UnnamedExpr(Expr::BinaryOp {
|
||||||
|
left: Box::new(Expr::Value(Value::Boolean(true))),
|
||||||
|
op: BinaryOperator::Xor,
|
||||||
|
right: Box::new(Expr::Value(Value::Boolean(true))),
|
||||||
|
}),
|
||||||
|
select.projection[0]
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
SelectItem::UnnamedExpr(Expr::BinaryOp {
|
||||||
|
left: Box::new(Expr::Value(Value::Boolean(false))),
|
||||||
|
op: BinaryOperator::Xor,
|
||||||
|
right: Box::new(Expr::Value(Value::Boolean(false))),
|
||||||
|
}),
|
||||||
|
select.projection[1]
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
SelectItem::UnnamedExpr(Expr::BinaryOp {
|
||||||
|
left: Box::new(Expr::Value(Value::Boolean(true))),
|
||||||
|
op: BinaryOperator::Xor,
|
||||||
|
right: Box::new(Expr::Value(Value::Boolean(false))),
|
||||||
|
}),
|
||||||
|
select.projection[2]
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
SelectItem::UnnamedExpr(Expr::BinaryOp {
|
||||||
|
left: Box::new(Expr::Value(Value::Boolean(false))),
|
||||||
|
op: BinaryOperator::Xor,
|
||||||
|
right: Box::new(Expr::Value(Value::Boolean(true))),
|
||||||
|
}),
|
||||||
|
select.projection[3]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_between() {
|
fn parse_between() {
|
||||||
fn chk(negated: bool) {
|
fn chk(negated: bool) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue