You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by al...@apache.org on 2022/11/08 21:39:58 UTC

[arrow-datafusion] branch master updated: support `SET Timezone` (#4107)

This is an automated email from the ASF dual-hosted git repository.

alamb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow-datafusion.git


The following commit(s) were added to refs/heads/master by this push:
     new e8fe04256 support `SET Timezone` (#4107)
e8fe04256 is described below

commit e8fe0425685e68826521c5a4e78d15d35f4556c2
Author: Wei-Ting Kuo <wa...@gmail.com>
AuthorDate: Wed Nov 9 05:39:53 2022 +0800

    support `SET Timezone` (#4107)
    
    * poc
    
    * fix test cases
    
    * fix examples, add more test cases
    
    * cargo fmt and clippy
    
    * clippy
---
 datafusion-examples/examples/rewrite_expr.rs   |   7 +
 datafusion/core/src/execution/context.rs       |   4 +
 datafusion/core/tests/sql/set_variable.rs      | 247 ++++++++++++++++++++++---
 datafusion/optimizer/tests/integration-test.rs |   7 +
 datafusion/sql/examples/sql.rs                 |   7 +
 datafusion/sql/src/planner.rs                  | 240 +++++++++++++-----------
 6 files changed, 377 insertions(+), 135 deletions(-)

diff --git a/datafusion-examples/examples/rewrite_expr.rs b/datafusion-examples/examples/rewrite_expr.rs
index d4a34e199..7a2ee6d93 100644
--- a/datafusion-examples/examples/rewrite_expr.rs
+++ b/datafusion-examples/examples/rewrite_expr.rs
@@ -148,6 +148,13 @@ impl ContextProvider for MyContextProvider {
     fn get_variable_type(&self, _variable_names: &[String]) -> Option<DataType> {
         None
     }
+
+    fn get_config_option(
+        &self,
+        _variable: &str,
+    ) -> Option<datafusion_common::ScalarValue> {
+        None
+    }
 }
 
 struct MyTableSource {
diff --git a/datafusion/core/src/execution/context.rs b/datafusion/core/src/execution/context.rs
index ec709f931..553a208b8 100644
--- a/datafusion/core/src/execution/context.rs
+++ b/datafusion/core/src/execution/context.rs
@@ -1818,6 +1818,10 @@ impl ContextProvider for SessionState {
             .as_ref()
             .and_then(|provider| provider.get(&provider_type)?.get_type(variable_names))
     }
+
+    fn get_config_option(&self, variable: &str) -> Option<ScalarValue> {
+        self.config.config_options.read().get(variable)
+    }
 }
 
 impl FunctionRegistry for SessionState {
diff --git a/datafusion/core/tests/sql/set_variable.rs b/datafusion/core/tests/sql/set_variable.rs
index 2bbe49120..085e7b1f4 100644
--- a/datafusion/core/tests/sql/set_variable.rs
+++ b/datafusion/core/tests/sql/set_variable.rs
@@ -260,37 +260,238 @@ async fn set_u64_variable_bad_value() {
 
 #[tokio::test]
 async fn set_time_zone() {
-    // we don't support changing time zone for now until all time zone issues fixed and related function completed
+    let ctx =
+        SessionContext::with_config(SessionConfig::new().with_information_schema(true));
 
-    let ctx = SessionContext::new();
+    plan_and_collect(&ctx, "SET datafusion.execution.time_zone = '+08:00'")
+        .await
+        .unwrap();
 
-    // for full variable name
-    let err = plan_and_collect(&ctx, "set datafusion.execution.time_zone = '8'")
+    let result = plan_and_collect(&ctx, "SHOW datafusion.execution.time_zone")
         .await
-        .unwrap_err();
+        .unwrap();
+    let expected = vec![
+        "+--------------------------------+---------+",
+        "| name                           | setting |",
+        "+--------------------------------+---------+",
+        "| datafusion.execution.time_zone | +08:00  |",
+        "+--------------------------------+---------+",
+    ];
+    assert_batches_eq!(expected, &result);
+}
 
-    assert_eq!(
-        err.to_string(),
-        "Error during planning: Changing Time Zone isn't supported yet"
-    );
+#[tokio::test]
+async fn set_time_zone_with_alias_variable_name() {
+    let ctx =
+        SessionContext::with_config(SessionConfig::new().with_information_schema(true));
 
-    // for alias time zone
-    let err = plan_and_collect(&ctx, "set time zone = '8'")
+    // TIME ZONE with space
+    plan_and_collect(&ctx, "SET TIME ZONE = '+08:00'")
         .await
-        .unwrap_err();
+        .unwrap();
 
-    assert_eq!(
-        err.to_string(),
-        "Error during planning: Changing Time Zone isn't supported yet"
-    );
+    let result = plan_and_collect(&ctx, "SHOW TIME ZONE").await.unwrap();
+    let expected = vec![
+        "+--------------------------------+---------+",
+        "| name                           | setting |",
+        "+--------------------------------+---------+",
+        "| datafusion.execution.time_zone | +08:00  |",
+        "+--------------------------------+---------+",
+    ];
+    assert_batches_eq!(expected, &result);
 
-    // for alias timezone
-    let err = plan_and_collect(&ctx, "set timezone = '8'")
+    // TIMEZONE without space
+    plan_and_collect(&ctx, "SET TIMEZONE = '+07:00'")
         .await
-        .unwrap_err();
+        .unwrap();
 
-    assert_eq!(
-        err.to_string(),
-        "Error during planning: Changing Time Zone isn't supported yet"
-    );
+    let result = plan_and_collect(&ctx, "SHOW TIMEZONE").await.unwrap();
+    let expected = vec![
+        "+--------------------------------+---------+",
+        "| name                           | setting |",
+        "+--------------------------------+---------+",
+        "| datafusion.execution.time_zone | +07:00  |",
+        "+--------------------------------+---------+",
+    ];
+    assert_batches_eq!(expected, &result);
+}
+
+#[tokio::test]
+async fn set_time_zone_good_time_zone_format() {
+    let ctx =
+        SessionContext::with_config(SessionConfig::new().with_information_schema(true));
+
+    plan_and_collect(&ctx, "SET TIME ZONE = '+08:00'")
+        .await
+        .unwrap();
+
+    // casting UTF-8 to TimestampTZ isn't supported yet, add Timestamp as the middle layer for now
+    let result =
+        plan_and_collect(&ctx, "SELECT '2000-01-01T00:00:00'::TIMESTAMP::TIMESTAMPTZ")
+            .await
+            .unwrap();
+    let expected = vec![
+        "+-----------------------------+",
+        "| Utf8(\"2000-01-01T00:00:00\") |",
+        "+-----------------------------+",
+        "| 2000-01-01T08:00:00+08:00   |",
+        "+-----------------------------+",
+    ];
+    // this might break once https://github.com/apache/arrow-rs/issues/1936 fixed
+    assert_batches_eq!(expected, &result);
+
+    plan_and_collect(&ctx, "SET TIME ZONE = '-08:00'")
+        .await
+        .unwrap();
+
+    // casting UTF-8 to TimestampTZ isn't supported yet, add Timestamp as the middle layer for now
+    let result =
+        plan_and_collect(&ctx, "SELECT '2000-01-01T00:00:00'::TIMESTAMP::TIMESTAMPTZ")
+            .await
+            .unwrap();
+    let expected = vec![
+        "+-----------------------------+",
+        "| Utf8(\"2000-01-01T00:00:00\") |",
+        "+-----------------------------+",
+        "| 1999-12-31T16:00:00-08:00   |",
+        "+-----------------------------+",
+    ];
+    // this might break once https://github.com/apache/arrow-rs/issues/1936 fixed
+    assert_batches_eq!(expected, &result);
+
+    plan_and_collect(&ctx, "SET TIME ZONE = '+0800'")
+        .await
+        .unwrap();
+
+    // casting UTF-8 to TimestampTZ isn't supported yet, add Timestamp as the middle layer for now
+    let result =
+        plan_and_collect(&ctx, "SELECT '2000-01-01T00:00:00'::TIMESTAMP::TIMESTAMPTZ")
+            .await
+            .unwrap();
+    let expected = vec![
+        "+-----------------------------+",
+        "| Utf8(\"2000-01-01T00:00:00\") |",
+        "+-----------------------------+",
+        "| 2000-01-01T08:00:00+08:00   |",
+        "+-----------------------------+",
+    ];
+    // this might break once https://github.com/apache/arrow-rs/issues/1936 fixed
+    assert_batches_eq!(expected, &result);
+
+    plan_and_collect(&ctx, "SET TIME ZONE = '+08'")
+        .await
+        .unwrap();
+
+    // casting UTF-8 to TimestampTZ isn't supported yet, add Timestamp as the middle layer for now
+    let result =
+        plan_and_collect(&ctx, "SELECT '2000-01-01T00:00:00'::TIMESTAMP::TIMESTAMPTZ")
+            .await
+            .unwrap();
+    let expected = vec![
+        "+-----------------------------+",
+        "| Utf8(\"2000-01-01T00:00:00\") |",
+        "+-----------------------------+",
+        "| 2000-01-01T08:00:00+08:00   |",
+        "+-----------------------------+",
+    ];
+    // this might break once https://github.com/apache/arrow-rs/issues/1936 fixed
+    assert_batches_eq!(expected, &result);
+}
+
+#[tokio::test]
+async fn set_time_zone_bad_time_zone_format() {
+    let ctx =
+        SessionContext::with_config(SessionConfig::new().with_information_schema(true));
+
+    plan_and_collect(&ctx, "SET TIME ZONE = '+08:00:00'")
+        .await
+        .unwrap();
+
+    // casting UTF-8 to TimestampTZ isn't supported yet, add Timestamp as the middle layer for now
+    let result =
+        plan_and_collect(&ctx, "SELECT '2000-01-01T00:00:00'::TIMESTAMP::TIMESTAMPTZ")
+            .await
+            .unwrap();
+    let expected = vec![
+        "+-----------------------------------------------------+",
+        "| Utf8(\"2000-01-01T00:00:00\")                         |",
+        "+-----------------------------------------------------+",
+        "| 2000-01-01T00:00:00 (Unknown Time Zone '+08:00:00') |",
+        "+-----------------------------------------------------+",
+    ];
+    assert_batches_eq!(expected, &result);
+
+    plan_and_collect(&ctx, "SET TIME ZONE = '08:00'")
+        .await
+        .unwrap();
+
+    // casting UTF-8 to TimestampTZ isn't supported yet, add Timestamp as the middle layer for now
+    let result =
+        plan_and_collect(&ctx, "SELECT '2000-01-01T00:00:00'::TIMESTAMP::TIMESTAMPTZ")
+            .await
+            .unwrap();
+    let expected = vec![
+        "+-------------------------------------------------+",
+        "| Utf8(\"2000-01-01T00:00:00\")                     |",
+        "+-------------------------------------------------+",
+        "| 2000-01-01T00:00:00 (Unknown Time Zone '08:00') |",
+        "+-------------------------------------------------+",
+    ];
+    assert_batches_eq!(expected, &result);
+
+    plan_and_collect(&ctx, "SET TIME ZONE = '08'")
+        .await
+        .unwrap();
+
+    // casting UTF-8 to TimestampTZ isn't supported yet, add Timestamp as the middle layer for now
+    let result =
+        plan_and_collect(&ctx, "SELECT '2000-01-01T00:00:00'::TIMESTAMP::TIMESTAMPTZ")
+            .await
+            .unwrap();
+    let expected = vec![
+        "+----------------------------------------------+",
+        "| Utf8(\"2000-01-01T00:00:00\")                  |",
+        "+----------------------------------------------+",
+        "| 2000-01-01T00:00:00 (Unknown Time Zone '08') |",
+        "+----------------------------------------------+",
+    ];
+    assert_batches_eq!(expected, &result);
+
+    // we dont support named time zone yet
+    plan_and_collect(&ctx, "SET TIME ZONE = 'Asia/Taipei'")
+        .await
+        .unwrap();
+
+    // casting UTF-8 to TimestampTZ isn't supported yet, add Timestamp as the middle layer for now
+    let result =
+        plan_and_collect(&ctx, "SELECT '2000-01-01T00:00:00'::TIMESTAMP::TIMESTAMPTZ")
+            .await
+            .unwrap();
+    let expected = vec![
+        "+-------------------------------------------------------+",
+        "| Utf8(\"2000-01-01T00:00:00\")                           |",
+        "+-------------------------------------------------------+",
+        "| 2000-01-01T00:00:00 (Unknown Time Zone 'Asia/Taipei') |",
+        "+-------------------------------------------------------+",
+    ];
+    assert_batches_eq!(expected, &result);
+
+    // this is invalid even after we support named time zone
+    plan_and_collect(&ctx, "SET TIME ZONE = 'Asia/Taipei2'")
+        .await
+        .unwrap();
+
+    // casting UTF-8 to TimestampTZ isn't supported yet, add Timestamp as the middle layer for now
+    let result =
+        plan_and_collect(&ctx, "SELECT '2000-01-01T00:00:00'::TIMESTAMP::TIMESTAMPTZ")
+            .await
+            .unwrap();
+    let expected = vec![
+        "+--------------------------------------------------------+",
+        "| Utf8(\"2000-01-01T00:00:00\")                            |",
+        "+--------------------------------------------------------+",
+        "| 2000-01-01T00:00:00 (Unknown Time Zone 'Asia/Taipei2') |",
+        "+--------------------------------------------------------+",
+    ];
+    assert_batches_eq!(expected, &result);
 }
diff --git a/datafusion/optimizer/tests/integration-test.rs b/datafusion/optimizer/tests/integration-test.rs
index b6931586e..be62ba2a5 100644
--- a/datafusion/optimizer/tests/integration-test.rs
+++ b/datafusion/optimizer/tests/integration-test.rs
@@ -330,6 +330,13 @@ impl ContextProvider for MySchemaProvider {
     fn get_variable_type(&self, _variable_names: &[String]) -> Option<DataType> {
         None
     }
+
+    fn get_config_option(
+        &self,
+        _variable: &str,
+    ) -> Option<datafusion_common::ScalarValue> {
+        None
+    }
 }
 
 fn observe(_plan: &LogicalPlan, _rule: &dyn OptimizerRule) {}
diff --git a/datafusion/sql/examples/sql.rs b/datafusion/sql/examples/sql.rs
index f03cad0b6..bc47348d5 100644
--- a/datafusion/sql/examples/sql.rs
+++ b/datafusion/sql/examples/sql.rs
@@ -120,4 +120,11 @@ impl ContextProvider for MySchemaProvider {
     fn get_variable_type(&self, _variable_names: &[String]) -> Option<DataType> {
         None
     }
+
+    fn get_config_option(
+        &self,
+        _variable: &str,
+    ) -> Option<datafusion_common::ScalarValue> {
+        None
+    }
 }
diff --git a/datafusion/sql/src/planner.rs b/datafusion/sql/src/planner.rs
index 1ecd110c0..58b216240 100644
--- a/datafusion/sql/src/planner.rs
+++ b/datafusion/sql/src/planner.rs
@@ -55,6 +55,7 @@ use datafusion_expr::expr::{Between, BinaryExpr, Case, Cast, GroupingSet, Like};
 use datafusion_expr::logical_plan::builder::project_with_alias;
 use datafusion_expr::logical_plan::{Filter, Subquery};
 use datafusion_expr::Expr::Alias;
+
 use sqlparser::ast::TimezoneInfo;
 use sqlparser::ast::{
     BinaryOperator, DataType as SQLDataType, DateTimeField, Expr as SQLExpr, FunctionArg,
@@ -88,6 +89,8 @@ pub trait ContextProvider {
     fn get_aggregate_meta(&self, name: &str) -> Option<Arc<AggregateUDF>>;
     /// Getter for system/user-defined variable type
     fn get_variable_type(&self, variable_names: &[String]) -> Option<DataType>;
+    /// Getter for config_options
+    fn get_config_option(&self, variable: &str) -> Option<ScalarValue>;
 }
 
 /// SQL query planner
@@ -558,7 +561,7 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
         let mut fields = Vec::with_capacity(columns.len());
 
         for column in columns {
-            let data_type = convert_simple_data_type(&column.data_type)?;
+            let data_type = self.convert_simple_data_type(&column.data_type)?;
             let allow_null = column
                 .options
                 .iter()
@@ -1721,7 +1724,7 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
                         SQLExpr::TypedString { data_type, value } => {
                             Ok(Expr::Cast(Cast::new(
                                 Box::new(lit(value)),
-                                convert_data_type(&data_type)?,
+                                self.convert_data_type(&data_type)?,
                             )))
                         }
                         SQLExpr::Cast { expr, data_type } => Ok(Expr::Cast(Cast::new(
@@ -1730,7 +1733,7 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
                                 &schema,
                                 &mut HashMap::new(),
                             )?),
-                            convert_data_type(&data_type)?,
+                            self.convert_data_type(&data_type)?,
                         ))),
                         other => Err(DataFusionError::NotImplemented(format!(
                             "Unsupported value {:?} in a values list expression",
@@ -1909,7 +1912,7 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
                 data_type,
             } => Ok(Expr::Cast(Cast::new(
                 Box::new(self.sql_expr_to_logical_expr(*expr, schema, ctes)?),
-                convert_data_type(&data_type)?,
+                self.convert_data_type(&data_type)?,
             ))),
 
             SQLExpr::TryCast {
@@ -1917,7 +1920,7 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
                 data_type,
             } => Ok(Expr::TryCast {
                 expr: Box::new(self.sql_expr_to_logical_expr(*expr, schema, ctes)?),
-                data_type: convert_data_type(&data_type)?,
+                data_type: self.convert_data_type(&data_type)?,
             }),
 
             SQLExpr::TypedString {
@@ -1925,7 +1928,7 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
                 value,
             } => Ok(Expr::Cast(Cast::new(
                 Box::new(lit(value)),
-                convert_data_type(&data_type)?,
+                self.convert_data_type(&data_type)?,
             ))),
 
             SQLExpr::IsNull(expr) => Ok(Expr::IsNull(Box::new(
@@ -2481,13 +2484,6 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
             variable_lower = "datafusion.execution.time_zone".to_string();
         }
 
-        // we don't support change time zone until we complete time zone related implementation
-        if variable_lower == "datafusion.execution.time_zone" {
-            return Err(DataFusionError::Plan(
-                "Changing Time Zone isn't supported yet".to_string(),
-            ));
-        }
-
         // parse value string from Expr
         let value_string = match &value[0] {
             SQLExpr::Identifier(i) => i.to_string(),
@@ -2671,6 +2667,121 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
             Ok(lit(ScalarValue::new_list(Some(values), data_type)))
         }
     }
+
+    fn convert_data_type(&self, sql_type: &SQLDataType) -> Result<DataType> {
+        match sql_type {
+            SQLDataType::Array(inner_sql_type) => {
+                let data_type = self.convert_simple_data_type(inner_sql_type)?;
+
+                Ok(DataType::List(Box::new(Field::new(
+                    "field", data_type, true,
+                ))))
+            }
+            other => self.convert_simple_data_type(other),
+        }
+    }
+    fn convert_simple_data_type(&self, sql_type: &SQLDataType) -> Result<DataType> {
+        match sql_type {
+            SQLDataType::Boolean => Ok(DataType::Boolean),
+            SQLDataType::TinyInt(_) => Ok(DataType::Int8),
+            SQLDataType::SmallInt(_) => Ok(DataType::Int16),
+            SQLDataType::Int(_) | SQLDataType::Integer(_) => Ok(DataType::Int32),
+            SQLDataType::BigInt(_) => Ok(DataType::Int64),
+            SQLDataType::UnsignedTinyInt(_) => Ok(DataType::UInt8),
+            SQLDataType::UnsignedSmallInt(_) => Ok(DataType::UInt16),
+            SQLDataType::UnsignedInt(_) | SQLDataType::UnsignedInteger(_) => {
+                Ok(DataType::UInt32)
+            }
+            SQLDataType::UnsignedBigInt(_) => Ok(DataType::UInt64),
+            SQLDataType::Float(_) => Ok(DataType::Float32),
+            SQLDataType::Real => Ok(DataType::Float32),
+            SQLDataType::Double | SQLDataType::DoublePrecision => Ok(DataType::Float64),
+            SQLDataType::Char(_)
+            | SQLDataType::Varchar(_)
+            | SQLDataType::Text
+            | SQLDataType::String => Ok(DataType::Utf8),
+            SQLDataType::Timestamp(tz_info) => {
+                let tz = if matches!(tz_info, TimezoneInfo::Tz)
+                    || matches!(tz_info, TimezoneInfo::WithTimeZone)
+                {
+                    // Timestamp With Time Zone
+                    // INPUT : [SQLDataType]   TimestampTz + [RuntimeConfig] Time Zone
+                    // OUTPUT: [ArrowDataType] Timestamp<TimeUnit, Some(Time Zone)>
+                    match self
+                        .schema_provider
+                        .get_config_option("datafusion.execution.time_zone")
+                    {
+                        Some(ScalarValue::Utf8(s)) => s,
+                        Some(v) => {
+                            return Err(DataFusionError::Internal(format!(
+                                "Incorrect data type for time_zone: {}",
+                                v.get_datatype(),
+                            )))
+                        }
+                        None => return Err(DataFusionError::Internal(
+                            "Config Option datafusion.execution.time_zone doesn't exist"
+                                .to_string(),
+                        )),
+                    }
+                } else {
+                    // Timestamp Without Time zone
+                    None
+                };
+                Ok(DataType::Timestamp(TimeUnit::Nanosecond, tz))
+            }
+            SQLDataType::Date => Ok(DataType::Date32),
+            SQLDataType::Time(tz_info) => {
+                if matches!(tz_info, TimezoneInfo::None)
+                    || matches!(tz_info, TimezoneInfo::WithoutTimeZone)
+                {
+                    Ok(DataType::Time64(TimeUnit::Nanosecond))
+                } else {
+                    // We dont support TIMETZ and TIME WITH TIME ZONE for now
+                    Err(DataFusionError::NotImplemented(format!(
+                        "Unsupported SQL type {:?}",
+                        sql_type
+                    )))
+                }
+            }
+            SQLDataType::Decimal(exact_number_info) => {
+                let (precision, scale) = match *exact_number_info {
+                    ExactNumberInfo::None => (None, None),
+                    ExactNumberInfo::Precision(precision) => (Some(precision), None),
+                    ExactNumberInfo::PrecisionAndScale(precision, scale) => {
+                        (Some(precision), Some(scale))
+                    }
+                };
+                make_decimal_type(precision, scale)
+            }
+            SQLDataType::Bytea => Ok(DataType::Binary),
+            // Explicitly list all other types so that if sqlparser
+            // adds/changes the `SQLDataType` the compiler will tell us on upgrade
+            // and avoid bugs like https://github.com/apache/arrow-datafusion/issues/3059
+            SQLDataType::Nvarchar(_)
+            | SQLDataType::Uuid
+            | SQLDataType::Binary(_)
+            | SQLDataType::Varbinary(_)
+            | SQLDataType::Blob(_)
+            | SQLDataType::Datetime
+            | SQLDataType::Interval
+            | SQLDataType::Regclass
+            | SQLDataType::Custom(_)
+            | SQLDataType::Array(_)
+            | SQLDataType::Enum(_)
+            | SQLDataType::Set(_)
+            | SQLDataType::MediumInt(_)
+            | SQLDataType::UnsignedMediumInt(_)
+            | SQLDataType::Character(_)
+            | SQLDataType::CharacterVarying(_)
+            | SQLDataType::CharVarying(_)
+            | SQLDataType::CharacterLargeObject(_)
+            | SQLDataType::CharLargeObject(_)
+            | SQLDataType::Clob(_) => Err(DataFusionError::NotImplemented(format!(
+                "Unsupported SQL type {:?}",
+                sql_type
+            ))),
+        }
+    }
 }
 
 /// Normalize a SQL object name
@@ -2808,105 +2919,6 @@ fn extract_possible_join_keys(
     }
 }
 
-/// Convert SQL simple data type to relational representation of data type
-pub fn convert_simple_data_type(sql_type: &SQLDataType) -> Result<DataType> {
-    match sql_type {
-        SQLDataType::Boolean => Ok(DataType::Boolean),
-        SQLDataType::TinyInt(_) => Ok(DataType::Int8),
-        SQLDataType::SmallInt(_) => Ok(DataType::Int16),
-        SQLDataType::Int(_) | SQLDataType::Integer(_) => Ok(DataType::Int32),
-        SQLDataType::BigInt(_) => Ok(DataType::Int64),
-        SQLDataType::UnsignedTinyInt(_) => Ok(DataType::UInt8),
-        SQLDataType::UnsignedSmallInt(_) => Ok(DataType::UInt16),
-        SQLDataType::UnsignedInt(_) | SQLDataType::UnsignedInteger(_) => {
-            Ok(DataType::UInt32)
-        }
-        SQLDataType::UnsignedBigInt(_) => Ok(DataType::UInt64),
-        SQLDataType::Float(_) => Ok(DataType::Float32),
-        SQLDataType::Real => Ok(DataType::Float32),
-        SQLDataType::Double | SQLDataType::DoublePrecision => Ok(DataType::Float64),
-        SQLDataType::Char(_)
-        | SQLDataType::Varchar(_)
-        | SQLDataType::Text
-        | SQLDataType::String => Ok(DataType::Utf8),
-        SQLDataType::Timestamp(tz_info) => {
-            let tz = if matches!(tz_info, TimezoneInfo::Tz)
-                || matches!(tz_info, TimezoneInfo::WithTimeZone)
-            {
-                Some("+00:00".to_string())
-            } else {
-                None
-            };
-            Ok(DataType::Timestamp(TimeUnit::Nanosecond, tz))
-        }
-        SQLDataType::Date => Ok(DataType::Date32),
-        SQLDataType::Time(tz_info) => {
-            if matches!(tz_info, TimezoneInfo::None)
-                || matches!(tz_info, TimezoneInfo::WithoutTimeZone)
-            {
-                Ok(DataType::Time64(TimeUnit::Nanosecond))
-            } else {
-                // We dont support TIMETZ and TIME WITH TIME ZONE for now
-                Err(DataFusionError::NotImplemented(format!(
-                    "Unsupported SQL type {:?}",
-                    sql_type
-                )))
-            }
-        }
-        SQLDataType::Decimal(exact_number_info) => {
-            let (precision, scale) = match *exact_number_info {
-                ExactNumberInfo::None => (None, None),
-                ExactNumberInfo::Precision(precision) => (Some(precision), None),
-                ExactNumberInfo::PrecisionAndScale(precision, scale) => {
-                    (Some(precision), Some(scale))
-                }
-            };
-            make_decimal_type(precision, scale)
-        }
-        SQLDataType::Bytea => Ok(DataType::Binary),
-        // Explicitly list all other types so that if sqlparser
-        // adds/changes the `SQLDataType` the compiler will tell us on upgrade
-        // and avoid bugs like https://github.com/apache/arrow-datafusion/issues/3059
-        SQLDataType::Nvarchar(_)
-        | SQLDataType::Uuid
-        | SQLDataType::Binary(_)
-        | SQLDataType::Varbinary(_)
-        | SQLDataType::Blob(_)
-        | SQLDataType::Datetime
-        | SQLDataType::Interval
-        | SQLDataType::Regclass
-        | SQLDataType::Custom(_)
-        | SQLDataType::Array(_)
-        | SQLDataType::Enum(_)
-        | SQLDataType::Set(_)
-        | SQLDataType::MediumInt(_)
-        | SQLDataType::UnsignedMediumInt(_)
-        | SQLDataType::Character(_)
-        | SQLDataType::CharacterVarying(_)
-        | SQLDataType::CharVarying(_)
-        | SQLDataType::CharacterLargeObject(_)
-        | SQLDataType::CharLargeObject(_)
-        | SQLDataType::Clob(_) => Err(DataFusionError::NotImplemented(format!(
-            "Unsupported SQL type {:?}",
-            sql_type
-        ))),
-    }
-}
-
-/// Convert SQL data type to relational representation of data type
-pub fn convert_data_type(sql_type: &SQLDataType) -> Result<DataType> {
-    match sql_type {
-        SQLDataType::Array(inner_sql_type) => {
-            let data_type = convert_simple_data_type(inner_sql_type)?;
-
-            Ok(DataType::List(Box::new(Field::new(
-                "field", data_type, true,
-            ))))
-        }
-        other => convert_simple_data_type(other),
-    }
-}
-
 // Parse number in sql string, convert to Expr::Literal
 fn parse_sql_number(n: &str) -> Result<Expr> {
     // parse first as i64
@@ -5014,6 +5026,10 @@ mod tests {
         fn get_variable_type(&self, _: &[String]) -> Option<DataType> {
             unimplemented!()
         }
+
+        fn get_config_option(&self, _: &str) -> Option<ScalarValue> {
+            unimplemented!()
+        }
     }
 
     #[test]