Skip to content

Commit 10830c5

Browse files
committed
Optionally parse numbers into BigDecimals
With `--features bigdecimal`, parse numbers into BigDecimals instead of leaving them as strings.
1 parent 44cd5f0 commit 10830c5

File tree

6 files changed

+94
-57
lines changed

6 files changed

+94
-57
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ name = "sqlparser"
1919
path = "src/lib.rs"
2020

2121
[dependencies]
22+
bigdecimal = { version = "0.1.0", optional = true }
2223
log = "0.4.5"
2324

2425
[dev-dependencies]

src/ast/value.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,18 @@
1010
// See the License for the specific language governing permissions and
1111
// limitations under the License.
1212

13+
#[cfg(feature = "bigdecimal")]
14+
use bigdecimal::BigDecimal;
1315
use std::fmt;
1416

1517
/// Primitive SQL values such as number and string
1618
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1719
pub enum Value {
1820
/// Numeric literal
21+
#[cfg(not(feature = "bigdecimal"))]
1922
Number(String),
23+
#[cfg(feature = "bigdecimal")]
24+
Number(BigDecimal),
2025
/// 'string value'
2126
SingleQuotedString(String),
2227
/// N'string value'

src/parser.rs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,7 +1183,13 @@ impl Parser {
11831183
return parser_err!(format!("No value parser for keyword {}", k.keyword));
11841184
}
11851185
},
1186-
Token::Number(ref n) => Ok(Value::Number(n.to_string())),
1186+
// The call to n.parse() returns a bigdecimal when the
1187+
// bigdecimal feature is enabled, and is otherwise a no-op
1188+
// (i.e., it returns the input string).
1189+
Token::Number(ref n) => match n.parse() {
1190+
Ok(n) => Ok(Value::Number(n)),
1191+
Err(e) => parser_err!(format!("Could not parse '{}' as number: {}", n, e)),
1192+
},
11871193
Token::SingleQuotedString(ref s) => Ok(Value::SingleQuotedString(s.to_string())),
11881194
Token::NationalStringLiteral(ref s) => {
11891195
Ok(Value::NationalStringLiteral(s.to_string()))
@@ -1195,6 +1201,16 @@ impl Parser {
11951201
}
11961202
}
11971203

1204+
pub fn parse_number_value(&mut self) -> Result<Value, ParserError> {
1205+
match self.parse_value()? {
1206+
v @ Value::Number(_) => Ok(v),
1207+
_ => {
1208+
self.prev_token();
1209+
self.expected("literal number", self.peek_token())
1210+
}
1211+
}
1212+
}
1213+
11981214
/// Parse an unsigned literal integer/long
11991215
pub fn parse_literal_uint(&mut self) -> Result<u64, ParserError> {
12001216
match self.next_token() {
@@ -1856,16 +1872,13 @@ impl Parser {
18561872
if self.parse_keyword("ALL") {
18571873
Ok(None)
18581874
} else {
1859-
self.parse_literal_uint()
1860-
.map(|n| Some(Expr::Value(Value::Number(n.to_string()))))
1875+
Ok(Some(Expr::Value(self.parse_number_value()?)))
18611876
}
18621877
}
18631878

18641879
/// Parse an OFFSET clause
18651880
pub fn parse_offset(&mut self) -> Result<Expr, ParserError> {
1866-
let value = self
1867-
.parse_literal_uint()
1868-
.map(|n| Expr::Value(Value::Number(n.to_string())))?;
1881+
let value = Expr::Value(self.parse_number_value()?);
18691882
self.expect_one_of_keywords(&["ROW", "ROWS"])?;
18701883
Ok(value)
18711884
}

src/test_utils.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,7 @@ pub fn expr_from_projection(item: &SelectItem) -> &Expr {
136136
_ => panic!("Expected UnnamedExpr"),
137137
}
138138
}
139+
140+
pub fn number(n: &'static str) -> Value {
141+
Value::Number(n.parse().unwrap())
142+
}

0 commit comments

Comments
 (0)