Skip to content

Commit 25718b8

Browse files
authored
Merge pull request #34 from nickolay/misc
Miscellaneous fixes
2 parents 2240dd0 + 3b13e15 commit 25718b8

File tree

2 files changed

+77
-126
lines changed

2 files changed

+77
-126
lines changed

Diff for: src/sqlparser.rs

+42-113
Original file line numberDiff line numberDiff line change
@@ -95,15 +95,7 @@ impl Parser {
9595
"INSERT" => Ok(self.parse_insert()?),
9696
"ALTER" => Ok(self.parse_alter()?),
9797
"COPY" => Ok(self.parse_copy()?),
98-
"TRUE" => {
99-
self.prev_token();
100-
self.parse_sql_value()
101-
}
102-
"FALSE" => {
103-
self.prev_token();
104-
self.parse_sql_value()
105-
}
106-
"NULL" => {
98+
"TRUE" | "FALSE" | "NULL" => {
10799
self.prev_token();
108100
self.parse_sql_value()
109101
}
@@ -116,7 +108,7 @@ impl Parser {
116108
self.parse_cast_expression()
117109
} else {
118110
match self.peek_token() {
119-
Some(Token::LParen) => self.parse_function_or_pg_cast(&id),
111+
Some(Token::LParen) => self.parse_function(&id),
120112
Some(Token::Period) => {
121113
let mut id_parts: Vec<String> = vec![id];
122114
while self.peek_token() == Some(Token::Period) {
@@ -136,19 +128,10 @@ impl Parser {
136128
}
137129
}
138130
}
139-
Token::Number(_) => {
140-
self.prev_token();
141-
self.parse_sql_value()
142-
}
143-
Token::String(_) => {
144-
self.prev_token();
145-
self.parse_sql_value()
146-
}
147-
Token::SingleQuotedString(_) => {
148-
self.prev_token();
149-
self.parse_sql_value()
150-
}
151-
Token::DoubleQuotedString(_) => {
131+
Token::Number(_)
132+
| Token::String(_)
133+
| Token::SingleQuotedString(_)
134+
| Token::DoubleQuotedString(_) => {
152135
self.prev_token();
153136
self.parse_sql_value()
154137
}
@@ -168,15 +151,6 @@ impl Parser {
168151
}
169152
}
170153

171-
pub fn parse_function_or_pg_cast(&mut self, id: &str) -> Result<ASTNode, ParserError> {
172-
let func = self.parse_function(&id)?;
173-
if let Some(Token::DoubleColon) = self.peek_token() {
174-
self.parse_pg_cast(func)
175-
} else {
176-
Ok(func)
177-
}
178-
}
179-
180154
pub fn parse_function(&mut self, id: &str) -> Result<ASTNode, ParserError> {
181155
self.consume_token(&Token::LParen)?;
182156
if let Ok(true) = self.consume_token(&Token::RParen) {
@@ -241,25 +215,13 @@ impl Parser {
241215
})
242216
}
243217

244-
/// Parse a postgresql casting style which is in the form or expr::datatype
218+
/// Parse a postgresql casting style which is in the form of `expr::datatype`
245219
pub fn parse_pg_cast(&mut self, expr: ASTNode) -> Result<ASTNode, ParserError> {
246220
let _ = self.consume_token(&Token::DoubleColon)?;
247-
let datatype = if let Ok(data_type) = self.parse_data_type() {
248-
Ok(data_type)
249-
} else if let Ok(table_name) = self.parse_tablename() {
250-
Ok(SQLType::Custom(table_name))
251-
} else {
252-
parser_err!("Expecting datatype or identifier")
253-
};
254-
let pg_cast = ASTNode::SQLCast {
221+
Ok(ASTNode::SQLCast {
255222
expr: Box::new(expr),
256-
data_type: datatype?,
257-
};
258-
if let Some(Token::DoubleColon) = self.peek_token() {
259-
self.parse_pg_cast(pg_cast)
260-
} else {
261-
Ok(pg_cast)
262-
}
223+
data_type: self.parse_data_type()?,
224+
})
263225
}
264226

265227
/// Parse an expression infix (typically an operator)
@@ -362,11 +324,17 @@ impl Parser {
362324
}
363325
}
364326

327+
/// Return first non-whitespace token that has not yet been processed
365328
pub fn peek_token(&self) -> Option<Token> {
366-
self.peek_token_skip_whitespace()
329+
if let Some(n) = self.til_non_whitespace() {
330+
self.token_at(n)
331+
} else {
332+
None
333+
}
367334
}
368335

369-
pub fn skip_whitespace(&mut self) -> Option<Token> {
336+
/// Get the next token skipping whitespace and increment the token index
337+
pub fn next_token(&mut self) -> Option<Token> {
370338
loop {
371339
match self.next_token_no_skip() {
372340
Some(Token::Whitespace(_)) => {
@@ -406,19 +374,6 @@ impl Parser {
406374
}
407375
}
408376

409-
pub fn peek_token_skip_whitespace(&self) -> Option<Token> {
410-
if let Some(n) = self.til_non_whitespace() {
411-
self.token_at(n)
412-
} else {
413-
None
414-
}
415-
}
416-
417-
/// Get the next token skipping whitespace and increment the token index
418-
pub fn next_token(&mut self) -> Option<Token> {
419-
self.skip_whitespace()
420-
}
421-
422377
pub fn next_token_no_skip(&mut self) -> Option<Token> {
423378
if self.index < self.tokens.len() {
424379
self.index = self.index + 1;
@@ -428,9 +383,9 @@ impl Parser {
428383
}
429384
}
430385

431-
/// if prev token is whitespace skip it
432-
/// if prev token is not whitespace skipt it as well
433-
pub fn prev_token_skip_whitespace(&mut self) -> Option<Token> {
386+
/// Push back the last one non-whitespace token
387+
pub fn prev_token(&mut self) -> Option<Token> {
388+
// TODO: returned value is unused (available via peek_token)
434389
loop {
435390
match self.prev_token_no_skip() {
436391
Some(Token::Whitespace(_)) => {
@@ -443,12 +398,8 @@ impl Parser {
443398
}
444399
}
445400

446-
pub fn prev_token(&mut self) -> Option<Token> {
447-
self.prev_token_skip_whitespace()
448-
}
449-
450401
/// Get the previous token and decrement the token index
451-
pub fn prev_token_no_skip(&mut self) -> Option<Token> {
402+
fn prev_token_no_skip(&mut self) -> Option<Token> {
452403
if self.index > 0 {
453404
self.index = self.index - 1;
454405
Some(self.tokens[self.index].clone())
@@ -731,30 +682,13 @@ impl Parser {
731682
"NULL" => Ok(Value::Null),
732683
_ => return parser_err!(format!("No value parser for keyword {}", k)),
733684
},
734-
//TODO: parse the timestamp here
685+
//TODO: parse the timestamp here (see parse_timestamp_value())
735686
Token::Number(ref n) if n.contains(".") => match n.parse::<f64>() {
736687
Ok(n) => Ok(Value::Double(n)),
737-
Err(e) => {
738-
let index = self.index;
739-
self.prev_token();
740-
if let Ok(timestamp) = self.parse_timestamp_value() {
741-
println!("timstamp: {:?}", timestamp);
742-
Ok(timestamp)
743-
} else {
744-
self.index = index;
745-
parser_err!(format!("Could not parse '{}' as i64: {}", n, e))
746-
}
747-
}
688+
Err(e) => parser_err!(format!("Could not parse '{}' as i64: {}", n, e)),
748689
},
749690
Token::Number(ref n) => match n.parse::<i64>() {
750-
Ok(n) => {
751-
// if let Some(Token::Minus) = self.peek_token() {
752-
// self.prev_token();
753-
// self.parse_timestamp_value()
754-
// } else {
755-
Ok(Value::Long(n))
756-
// }
757-
}
691+
Ok(n) => Ok(Value::Long(n)),
758692
Err(e) => parser_err!(format!("Could not parse '{}' as i64: {}", n, e)),
759693
},
760694
Token::Identifier(id) => Ok(Value::String(id.to_string())),
@@ -782,13 +716,13 @@ impl Parser {
782716
}
783717
}
784718

785-
/// Parse a literal integer/long
719+
/// Parse a literal double
786720
pub fn parse_literal_double(&mut self) -> Result<f64, ParserError> {
787721
match self.next_token() {
788722
Some(Token::Number(s)) => s.parse::<f64>().map_err(|e| {
789-
ParserError::ParserError(format!("Could not parse '{}' as i64: {}", s, e))
723+
ParserError::ParserError(format!("Could not parse '{}' as f64: {}", s, e))
790724
}),
791-
other => parser_err!(format!("Expected literal int, found {:?}", other)),
725+
other => parser_err!(format!("Expected literal number, found {:?}", other)),
792726
}
793727
}
794728

@@ -869,19 +803,17 @@ impl Parser {
869803
self.consume_token(&Token::Colon)?;
870804
let min = self.parse_literal_int()?;
871805
self.consume_token(&Token::Colon)?;
806+
// On one hand, the SQL specs defines <seconds fraction> ::= <unsigned integer>,
807+
// so it would be more correct to parse it as such
872808
let sec = self.parse_literal_double()?;
873-
let _ = (sec.fract() * 1000.0).round();
874-
if let Ok(true) = self.consume_token(&Token::Period) {
875-
let ms = self.parse_literal_int()?;
876-
Ok(NaiveTime::from_hms_milli(
877-
hour as u32,
878-
min as u32,
879-
sec as u32,
880-
ms as u32,
881-
))
882-
} else {
883-
Ok(NaiveTime::from_hms(hour as u32, min as u32, sec as u32))
884-
}
809+
// On the other, chrono only supports nanoseconds, which should(?) fit in seconds-as-f64...
810+
let nanos = (sec.fract() * 1_000_000_000.0).round();
811+
Ok(NaiveTime::from_hms_nano(
812+
hour as u32,
813+
min as u32,
814+
sec as u32,
815+
nanos as u32,
816+
))
885817
}
886818

887819
/// Parse a SQL datatype (in the context of a CREATE TABLE statement for example)
@@ -973,13 +905,10 @@ impl Parser {
973905
}
974906
_ => parser_err!(format!("Invalid data type '{:?}'", k)),
975907
},
976-
Some(Token::Identifier(id)) => {
977-
if let Ok(true) = self.consume_token(&Token::Period) {
978-
let ids = self.parse_tablename()?;
979-
Ok(SQLType::Custom(format!("{}.{}", id, ids)))
980-
} else {
981-
Ok(SQLType::Custom(id))
982-
}
908+
Some(Token::Identifier(_)) => {
909+
self.prev_token();
910+
let type_name = self.parse_tablename()?; // TODO: this actually reads a possibly schema-qualified name of a (custom) type
911+
Ok(SQLType::Custom(type_name))
983912
}
984913
other => parser_err!(format!("Invalid data type: '{:?}'", other)),
985914
}

Diff for: tests/sqlparser_postgres.rs

+35-13
Original file line numberDiff line numberDiff line change
@@ -517,20 +517,40 @@ fn parse_create_table_from_pg_dump() {
517517
ASTNode::SQLCreateTable { name, columns } => {
518518
assert_eq!("public.customer", name);
519519

520-
let c_name = &columns[0];
521-
assert_eq!("customer_id", c_name.name);
522-
assert_eq!(SQLType::Int, c_name.data_type);
523-
assert_eq!(false, c_name.allow_null);
524-
525-
let c_lat = &columns[1];
526-
assert_eq!("store_id", c_lat.name);
527-
assert_eq!(SQLType::SmallInt, c_lat.data_type);
528-
assert_eq!(false, c_lat.allow_null);
520+
let c_customer_id = &columns[0];
521+
assert_eq!("customer_id", c_customer_id.name);
522+
assert_eq!(SQLType::Int, c_customer_id.data_type);
523+
assert_eq!(false, c_customer_id.allow_null);
524+
525+
let c_store_id = &columns[1];
526+
assert_eq!("store_id", c_store_id.name);
527+
assert_eq!(SQLType::SmallInt, c_store_id.data_type);
528+
assert_eq!(false, c_store_id.allow_null);
529+
530+
let c_first_name = &columns[2];
531+
assert_eq!("first_name", c_first_name.name);
532+
assert_eq!(SQLType::Varchar(Some(45)), c_first_name.data_type);
533+
assert_eq!(false, c_first_name.allow_null);
534+
535+
let c_create_date1 = &columns[8];
536+
assert_eq!(
537+
Some(Box::new(ASTNode::SQLCast {
538+
expr: Box::new(ASTNode::SQLCast {
539+
expr: Box::new(ASTNode::SQLValue(Value::SingleQuotedString(
540+
"now".to_string()
541+
))),
542+
data_type: SQLType::Text
543+
}),
544+
data_type: SQLType::Date
545+
})),
546+
c_create_date1.default
547+
);
529548

530-
let c_lng = &columns[2];
531-
assert_eq!("first_name", c_lng.name);
532-
assert_eq!(SQLType::Varchar(Some(45)), c_lng.data_type);
533-
assert_eq!(false, c_lng.allow_null);
549+
let c_release_year = &columns[10];
550+
assert_eq!(
551+
SQLType::Custom("public.year".to_string()),
552+
c_release_year.data_type
553+
);
534554
}
535555
_ => assert!(false),
536556
}
@@ -637,13 +657,15 @@ fn parse_timestamps_example() {
637657
let sql = "2016-02-15 09:43:33";
638658
let _ = parse_sql(sql);
639659
//TODO add assertion
660+
//assert_eq!(sql, ast.to_string());
640661
}
641662

642663
#[test]
643664
fn parse_timestamps_with_millis_example() {
644665
let sql = "2017-11-02 19:15:42.308637";
645666
let _ = parse_sql(sql);
646667
//TODO add assertion
668+
//assert_eq!(sql, ast.to_string());
647669
}
648670

649671
#[test]

0 commit comments

Comments
 (0)