Skip to content

Commit 046da82

Browse files
committed
fix regression
1 parent fc03001 commit 046da82

File tree

1 file changed

+63
-18
lines changed

1 file changed

+63
-18
lines changed

datafusion/sql/src/planner.rs

Lines changed: 63 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,24 @@ pub trait ContextProvider {
9090
fn get_variable_type(&self, variable_names: &[String]) -> Option<DataType>;
9191
}
9292

93+
/// SQL parser options
94+
#[derive(Debug)]
95+
struct ParserOptions {
96+
parse_float_as_decimal: bool,
97+
}
98+
99+
impl Default for ParserOptions {
100+
fn default() -> Self {
101+
Self {
102+
parse_float_as_decimal: false,
103+
}
104+
}
105+
}
106+
93107
/// SQL query planner
94108
pub struct SqlToRel<'a, S: ContextProvider> {
95109
schema_provider: &'a S,
110+
options: ParserOptions,
96111
}
97112

98113
fn plan_key(key: SQLExpr) -> Result<ScalarValue> {
@@ -135,7 +150,10 @@ fn plan_indexed(expr: Expr, mut keys: Vec<SQLExpr>) -> Result<Expr> {
135150
impl<'a, S: ContextProvider> SqlToRel<'a, S> {
136151
/// Create a new query planner
137152
pub fn new(schema_provider: &'a S) -> Self {
138-
SqlToRel { schema_provider }
153+
SqlToRel {
154+
schema_provider,
155+
options: ParserOptions::default(),
156+
}
139157
}
140158

141159
/// Generate a logical plan from an DataFusion SQL statement
@@ -1696,7 +1714,7 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
16961714
.map(|row| {
16971715
row.into_iter()
16981716
.map(|v| match v {
1699-
SQLExpr::Value(Value::Number(n, _)) => parse_sql_number(&n),
1717+
SQLExpr::Value(Value::Number(n, _)) => self.parse_sql_number(&n),
17001718
SQLExpr::Value(
17011719
Value::SingleQuotedString(s) | Value::DoubleQuotedString(s),
17021720
) => Ok(lit(s)),
@@ -1750,7 +1768,7 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
17501768
ctes: &mut HashMap<String, LogicalPlan>,
17511769
) -> Result<Expr> {
17521770
match sql {
1753-
SQLExpr::Value(Value::Number(n, _)) => parse_sql_number(&n),
1771+
SQLExpr::Value(Value::Number(n, _)) => self.parse_sql_number(&n),
17541772
SQLExpr::Value(Value::SingleQuotedString(ref s) | Value::DoubleQuotedString(ref s)) => Ok(lit(s.clone())),
17551773
SQLExpr::Value(Value::Boolean(n)) => Ok(lit(n)),
17561774
SQLExpr::Value(Value::Null) => Ok(Expr::Literal(ScalarValue::Null)),
@@ -2671,6 +2689,48 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
26712689
Ok(lit(ScalarValue::new_list(Some(values), data_type)))
26722690
}
26732691
}
2692+
2693+
/// Parse number in sql string, convert to Expr::Literal
2694+
fn parse_sql_number(&self, n: &str) -> Result<Expr> {
2695+
if let Some(i) = n.find('E') {
2696+
let _mantissa = &n[0..i];
2697+
let _exponent = &n[i + 1..];
2698+
Err(DataFusionError::NotImplemented(
2699+
"sql numeric literals in scientific notation are not supported"
2700+
.to_string(),
2701+
))
2702+
} else if let Ok(n) = n.parse::<i64>() {
2703+
Ok(lit(n))
2704+
} else if self.options.parse_float_as_decimal {
2705+
if let Some(i) = n.find('.') {
2706+
let p = n.len() - 1;
2707+
let s = n.len() - i - 1;
2708+
let str = n.replace('.', "");
2709+
let n = str.parse::<i128>().map_err(|_| {
2710+
DataFusionError::from(ParserError(format!(
2711+
"Cannot parse {} as i128 when building decimal",
2712+
str
2713+
)))
2714+
})?;
2715+
Ok(Expr::Literal(ScalarValue::Decimal128(
2716+
Some(n),
2717+
p as u8,
2718+
s as u8,
2719+
)))
2720+
} else {
2721+
n.parse::<f64>().map(lit).map_err(|_| {
2722+
DataFusionError::from(ParserError(format!(
2723+
"Cannot parse {} as f64",
2724+
n
2725+
)))
2726+
})
2727+
}
2728+
} else {
2729+
n.parse::<f64>().map(lit).map_err(|_| {
2730+
DataFusionError::from(ParserError(format!("Cannot parse {} as f64", n)))
2731+
})
2732+
}
2733+
}
26742734
}
26752735

26762736
/// Normalize a SQL object name
@@ -2907,21 +2967,6 @@ pub fn convert_data_type(sql_type: &SQLDataType) -> Result<DataType> {
29072967
}
29082968
}
29092969

2910-
// Parse number in sql string, convert to Expr::Literal
2911-
fn parse_sql_number(n: &str) -> Result<Expr> {
2912-
// parse first as i64
2913-
n.parse::<i64>()
2914-
.map(lit)
2915-
// if parsing as i64 fails try f64
2916-
.or_else(|_| n.parse::<f64>().map(lit))
2917-
.map_err(|_| {
2918-
DataFusionError::from(ParserError(format!(
2919-
"Cannot parse {} as i64 or f64",
2920-
n
2921-
)))
2922-
})
2923-
}
2924-
29252970
#[cfg(test)]
29262971
mod tests {
29272972
use super::*;

0 commit comments

Comments
 (0)