@@ -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
94108pub struct SqlToRel < ' a , S : ContextProvider > {
95109 schema_provider : & ' a S ,
110+ options : ParserOptions ,
96111}
97112
98113fn plan_key ( key : SQLExpr ) -> Result < ScalarValue > {
@@ -135,7 +150,10 @@ fn plan_indexed(expr: Expr, mut keys: Vec<SQLExpr>) -> Result<Expr> {
135150impl < ' 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) ]
29262971mod tests {
29272972 use super :: * ;
0 commit comments