Merge pull request #32 from cswinter/like

Add LIKE operator
This commit is contained in:
Andy Grove 2018-12-16 13:54:00 -07:00 committed by GitHub
commit 24af049930
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 28 additions and 4 deletions

View file

@ -11,7 +11,7 @@ impl Dialect for GenericSqlDialect {
STORED, CSV, PARQUET, LOCATION, WITH, WITHOUT, HEADER, ROW, // SQL types
CHAR, CHARACTER, VARYING, LARGE, OBJECT, VARCHAR, CLOB, BINARY, VARBINARY, BLOB, FLOAT,
REAL, DOUBLE, PRECISION, INT, INTEGER, SMALLINT, BIGINT, NUMERIC, DECIMAL, DEC,
BOOLEAN, DATE, TIME, TIMESTAMP, CASE, WHEN, THEN, ELSE, END,
BOOLEAN, DATE, TIME, TIMESTAMP, CASE, WHEN, THEN, ELSE, END, LIKE,
];
}

View file

@ -14,7 +14,7 @@ impl Dialect for PostgreSqlDialect {
DOUBLE, PRECISION, INT, INTEGER, SMALLINT, BIGINT, NUMERIC, DECIMAL, DEC, BOOLEAN,
DATE, TIME, TIMESTAMP, VALUES, DEFAULT, ZONE, REGCLASS, TEXT, BYTEA, TRUE, FALSE, COPY,
STDIN, PRIMARY, KEY, UNIQUE, UUID, ADD, CONSTRAINT, FOREIGN, REFERENCES,
CASE, WHEN, THEN, ELSE, END,
CASE, WHEN, THEN, ELSE, END, LIKE,
];
}

View file

@ -14,6 +14,7 @@ pub enum SQLOperator {
NotEq,
And,
Or,
Like,
}
impl ToString for SQLOperator {
@ -32,6 +33,7 @@ impl ToString for SQLOperator {
SQLOperator::NotEq => "!=".to_string(),
SQLOperator::And => "AND".to_string(),
SQLOperator::Or => "OR".to_string(),
SQLOperator::Like => "LIKE".to_string(),
}
}
}

View file

@ -18,7 +18,7 @@ use super::dialect::Dialect;
use super::sqlast::*;
use super::sqltokenizer::*;
use chrono::{
offset::{FixedOffset},
offset::FixedOffset,
DateTime, NaiveDate, NaiveDateTime, NaiveTime,
};
@ -334,6 +334,7 @@ impl Parser {
&Token::Mod => Ok(SQLOperator::Modulus),
&Token::Keyword(ref k) if k == "AND" => Ok(SQLOperator::And),
&Token::Keyword(ref k) if k == "OR" => Ok(SQLOperator::Or),
&Token::Keyword(ref k) if k == "LIKE" => Ok(SQLOperator::Like),
_ => parser_err!(format!("Unsupported SQL operator {:?}", tok)),
}
}
@ -355,6 +356,7 @@ impl Parser {
&Token::Keyword(ref k) if k == "OR" => Ok(5),
&Token::Keyword(ref k) if k == "AND" => Ok(10),
&Token::Keyword(ref k) if k == "IS" => Ok(15),
&Token::Keyword(ref k )if k == "LIKE" => Ok(20),
&Token::Eq | &Token::Lt | &Token::LtEq | &Token::Neq | &Token::Gt | &Token::GtEq => {
Ok(20)
}

View file

@ -23,7 +23,7 @@ fn parse_simple_select() {
fn parse_sql(sql: &str) -> ASTNode {
let dialect = AnsiSqlDialect {};
let mut tokenizer = Tokenizer::new(&dialect,&sql, );
let mut tokenizer = Tokenizer::new(&dialect, &sql);
let tokens = tokenizer.tokenize().unwrap();
let mut parser = Parser::new(tokens);
let ast = parser.parse().unwrap();

View file

@ -730,3 +730,23 @@ fn parser(sql: &str) -> Parser {
debug!("tokens: {:#?}", tokens);
Parser::new(tokens)
}
#[test]
fn parse_like() {
let sql = String::from("SELECT * FROM customers WHERE name LIKE '%a'");
let ast = parse_sql(&sql);
assert_eq!(sql, ast.to_string());
match ast {
ASTNode::SQLSelect { selection, .. } => {
assert_eq!(
ASTNode::SQLBinaryExpr {
left: Box::new(ASTNode::SQLIdentifier("name".to_string())),
op: SQLOperator::Like,
right: Box::new(ASTNode::SQLValue(Value::SingleQuotedString("%a".to_string()))),
},
*selection.unwrap()
);
}
_ => assert!(false),
}
}