Skip to content

Commit 9733e2e

Browse files
committed
Add spaceship operator
1 parent df21533 commit 9733e2e

File tree

4 files changed

+24
-14
lines changed

4 files changed

+24
-14
lines changed

src/ast/operator.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ pub enum BinaryOperator {
4747
Lt,
4848
GtEq,
4949
LtEq,
50+
Spaceship,
5051
Eq,
5152
NotEq,
5253
And,
@@ -71,6 +72,7 @@ impl fmt::Display for BinaryOperator {
7172
BinaryOperator::Lt => "<",
7273
BinaryOperator::GtEq => ">=",
7374
BinaryOperator::LtEq => "<=",
75+
BinaryOperator::Spaceship => "<=>",
7476
BinaryOperator::Eq => "=",
7577
BinaryOperator::NotEq => "<>",
7678
BinaryOperator::And => "AND",

src/parser.rs

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ pub enum IsLateral {
5757
}
5858
use crate::ast::Statement::CreateVirtualTable;
5959
use IsLateral::*;
60-
use crate::ast::Expr::BinaryOp;
60+
6161

6262
impl From<TokenizerError> for ParserError {
6363
fn from(e: TokenizerError) -> Self {
@@ -382,15 +382,7 @@ impl Parser {
382382
self.expect_token(&Token::RParen)?;
383383
Ok(expr)
384384
}
385-
unexpected => {
386-
self.prev_token();
387-
self.prev_token();
388-
self.prev_token();
389-
let t1 = self.next_token().to_string();
390-
let t2 = self.next_token().to_string();
391-
let t3 = self.next_token().to_string();
392-
self.expected(format!("an expression: {} - {} {} {}", self.index, &t1, &t2, &t3).as_str(), unexpected)
393-
},
385+
unexpected => self.expected("an expression:", unexpected),
394386
}?;
395387

396388
if self.parse_keyword(Keyword::COLLATE) {
@@ -721,6 +713,7 @@ impl Parser {
721713
pub fn parse_infix(&mut self, expr: Expr, precedence: u8) -> Result<Expr, ParserError> {
722714
let tok = self.next_token();
723715
let regular_binary_operator = match &tok {
716+
Token::Spaceship => Some(BinaryOperator::Spaceship),
724717
Token::DoubleEq => Some(BinaryOperator::Eq),
725718
Token::Eq => Some(BinaryOperator::Eq),
726719
Token::Neq => Some(BinaryOperator::NotEq),
@@ -862,7 +855,7 @@ impl Parser {
862855
Token::Word(w) if w.keyword == Keyword::IN => Ok(Self::BETWEEN_PREC),
863856
Token::Word(w) if w.keyword == Keyword::BETWEEN => Ok(Self::BETWEEN_PREC),
864857
Token::Word(w) if w.keyword == Keyword::LIKE => Ok(Self::BETWEEN_PREC),
865-
Token::Eq | Token::Lt | Token::LtEq | Token::Neq | Token::Gt | Token::GtEq | Token::DoubleEq => Ok(20),
858+
Token::Eq | Token::Lt | Token::LtEq | Token::Neq | Token::Gt | Token::GtEq | Token::DoubleEq | Token::Spaceship => Ok(20),
866859
Token::Pipe => Ok(21),
867860
Token::Caret => Ok(22),
868861
Token::Ampersand => Ok(23),

src/tokenizer.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ pub enum Token {
5858
LtEq,
5959
/// Greater Than Or Equals operator `>=`
6060
GtEq,
61+
/// Spaceship operator <=>
62+
Spaceship,
6163
/// Plus operator `+`
6264
Plus,
6365
/// Minus operator `-`
@@ -113,6 +115,7 @@ impl fmt::Display for Token {
113115
Token::Comma => f.write_str(","),
114116
Token::Whitespace(ws) => write!(f, "{}", ws),
115117
Token::DoubleEq => f.write_str("=="),
118+
Token::Spaceship => f.write_str("<=>"),
116119
Token::Eq => f.write_str("="),
117120
Token::Neq => f.write_str("<>"),
118121
Token::Lt => f.write_str("<"),
@@ -416,7 +419,13 @@ impl<'a> Tokenizer<'a> {
416419
'<' => {
417420
chars.next(); // consume
418421
match chars.peek() {
419-
Some('=') => self.consume_and_return(chars, Token::LtEq),
422+
Some('=') => {
423+
chars.next();
424+
match chars.peek() {
425+
Some('>') => self.consume_and_return(chars, Token::Spaceship),
426+
_ => Ok(Some(Token::LtEq))
427+
}
428+
},
420429
Some('>') => self.consume_and_return(chars, Token::Neq),
421430
_ => Ok(Some(Token::Lt)),
422431
}

tests/sqlparser_hive.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@
1515
//! Test SQL syntax specific to Hive. The parser based on the generic dialect
1616
//! is also tested (on the inputs it can handle).
1717
18-
use sqlparser::ast::*;
18+
1919
use sqlparser::dialect::{GenericDialect, HiveDialect};
2020
use sqlparser::test_utils::*;
21-
use sqlparser::parser::ParserError;
21+
2222

2323
#[test]
2424
fn parse_table_create() {
@@ -59,6 +59,12 @@ fn parse_set() {
5959
hive().verified_stmt(set);
6060
}
6161

62+
#[test]
63+
fn test_spaceship() {
64+
let spaceship = "SELECT * FROM db.table WHERE a <=> b";
65+
hive().verified_stmt(spaceship);
66+
}
67+
6268
#[test]
6369
fn parse_with_cte() {
6470
let with = "WITH a AS (SELECT * FROM table) INSERT INTO TABLE db.table_table PARTITION (a) SELECT * FROM a";

0 commit comments

Comments
 (0)