diff --git a/src/sqlparser.rs b/src/sqlparser.rs index ead70a78..c7733b57 100644 --- a/src/sqlparser.rs +++ b/src/sqlparser.rs @@ -682,30 +682,13 @@ impl Parser { "NULL" => Ok(Value::Null), _ => return parser_err!(format!("No value parser for keyword {}", k)), }, - //TODO: parse the timestamp here + //TODO: parse the timestamp here (see parse_timestamp_value()) Token::Number(ref n) if n.contains(".") => match n.parse::() { Ok(n) => Ok(Value::Double(n)), - Err(e) => { - let index = self.index; - self.prev_token(); - if let Ok(timestamp) = self.parse_timestamp_value() { - println!("timstamp: {:?}", timestamp); - Ok(timestamp) - } else { - self.index = index; - parser_err!(format!("Could not parse '{}' as i64: {}", n, e)) - } - } + Err(e) => parser_err!(format!("Could not parse '{}' as i64: {}", n, e)), }, Token::Number(ref n) => match n.parse::() { - Ok(n) => { - // if let Some(Token::Minus) = self.peek_token() { - // self.prev_token(); - // self.parse_timestamp_value() - // } else { - Ok(Value::Long(n)) - // } - } + Ok(n) => Ok(Value::Long(n)), Err(e) => parser_err!(format!("Could not parse '{}' as i64: {}", n, e)), }, Token::Identifier(id) => Ok(Value::String(id.to_string())), @@ -733,13 +716,13 @@ impl Parser { } } - /// Parse a literal integer/long + /// Parse a literal double pub fn parse_literal_double(&mut self) -> Result { match self.next_token() { Some(Token::Number(s)) => s.parse::().map_err(|e| { - ParserError::ParserError(format!("Could not parse '{}' as i64: {}", s, e)) + ParserError::ParserError(format!("Could not parse '{}' as f64: {}", s, e)) }), - other => parser_err!(format!("Expected literal int, found {:?}", other)), + other => parser_err!(format!("Expected literal number, found {:?}", other)), } } @@ -820,19 +803,17 @@ impl Parser { self.consume_token(&Token::Colon)?; let min = self.parse_literal_int()?; self.consume_token(&Token::Colon)?; + // On one hand, the SQL specs defines ::= , + // so it would be more correct to parse it as such let sec = self.parse_literal_double()?; - let _ = (sec.fract() * 1000.0).round(); - if let Ok(true) = self.consume_token(&Token::Period) { - let ms = self.parse_literal_int()?; - Ok(NaiveTime::from_hms_milli( - hour as u32, - min as u32, - sec as u32, - ms as u32, - )) - } else { - Ok(NaiveTime::from_hms(hour as u32, min as u32, sec as u32)) - } + // On the other, chrono only supports nanoseconds, which should(?) fit in seconds-as-f64... + let nanos = (sec.fract() * 1_000_000_000.0).round(); + Ok(NaiveTime::from_hms_nano( + hour as u32, + min as u32, + sec as u32, + nanos as u32, + )) } /// Parse a SQL datatype (in the context of a CREATE TABLE statement for example) diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index 49619075..34370583 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -657,6 +657,7 @@ fn parse_timestamps_example() { let sql = "2016-02-15 09:43:33"; let _ = parse_sql(sql); //TODO add assertion + //assert_eq!(sql, ast.to_string()); } #[test] @@ -664,6 +665,7 @@ fn parse_timestamps_with_millis_example() { let sql = "2017-11-02 19:15:42.308637"; let _ = parse_sql(sql); //TODO add assertion + //assert_eq!(sql, ast.to_string()); } #[test]