mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-09-01 11:47:20 +00:00
Don't lose precision when parsing decimal fractions
The SQL standard requires that numeric literals with a decimal point, like 1.23, are represented exactly, up to some precision. That means that parsing these literals into f64s is invalid, as it is impossible to represent many decimal numbers exactly in binary floating point (for example, 0.3). This commit parses all numeric literals into a new `Value` variant `Number(String)`, removing the old `Long(u64)` and `Double(f64)` variants. This is slightly less convenient for downstream consumers, but far more flexible, as numbers that do not fit into a u64 and f64 are now representable.
This commit is contained in:
parent
2bef9ec30a
commit
b5621c0fe8
5 changed files with 82 additions and 77 deletions
|
@ -1183,14 +1183,7 @@ impl Parser {
|
|||
return parser_err!(format!("No value parser for keyword {}", k.keyword));
|
||||
}
|
||||
},
|
||||
Token::Number(ref n) if n.contains('.') => match n.parse::<f64>() {
|
||||
Ok(n) => Ok(Value::Double(n.into())),
|
||||
Err(e) => parser_err!(format!("Could not parse '{}' as f64: {}", n, e)),
|
||||
},
|
||||
Token::Number(ref n) => match n.parse::<u64>() {
|
||||
Ok(n) => Ok(Value::Long(n)),
|
||||
Err(e) => parser_err!(format!("Could not parse '{}' as u64: {}", n, e)),
|
||||
},
|
||||
Token::Number(ref n) => Ok(Value::Number(n.to_string())),
|
||||
Token::SingleQuotedString(ref s) => Ok(Value::SingleQuotedString(s.to_string())),
|
||||
Token::NationalStringLiteral(ref s) => {
|
||||
Ok(Value::NationalStringLiteral(s.to_string()))
|
||||
|
@ -1864,7 +1857,7 @@ impl Parser {
|
|||
Ok(None)
|
||||
} else {
|
||||
self.parse_literal_uint()
|
||||
.map(|n| Some(Expr::Value(Value::Long(n))))
|
||||
.map(|n| Some(Expr::Value(Value::Number(n.to_string()))))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1872,7 +1865,7 @@ impl Parser {
|
|||
pub fn parse_offset(&mut self) -> Result<Expr, ParserError> {
|
||||
let value = self
|
||||
.parse_literal_uint()
|
||||
.map(|n| Expr::Value(Value::Long(n)))?;
|
||||
.map(|n| Expr::Value(Value::Number(n.to_string())))?;
|
||||
self.expect_one_of_keywords(&["ROW", "ROWS"])?;
|
||||
Ok(value)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue