From b65daed0979f5fb79f390009c34ddb3b496a2232 Mon Sep 17 00:00:00 2001 From: Wei-Ting Kuo Date: Tue, 13 Sep 2022 03:58:45 +0800 Subject: [PATCH 1/5] support "SHOW VARIABLE;" --- .../core/src/catalog/information_schema.rs | 82 ++++++++++++++++++- datafusion/core/src/execution/context.rs | 30 ++++--- datafusion/core/src/physical_plan/planner.rs | 2 + .../core/tests/sql/information_schema.rs | 80 ++++++++++++++++-- datafusion/sql/src/planner.rs | 25 +++++- 5 files changed, 194 insertions(+), 25 deletions(-) diff --git a/datafusion/core/src/catalog/information_schema.rs b/datafusion/core/src/catalog/information_schema.rs index 00b7d7d35a74..92450ddbce4a 100644 --- a/datafusion/core/src/catalog/information_schema.rs +++ b/datafusion/core/src/catalog/information_schema.rs @@ -24,6 +24,8 @@ use std::{ sync::{Arc, Weak}, }; +use parking_lot::RwLock; + use arrow::{ array::{StringBuilder, UInt64Builder}, datatypes::{DataType, Field, Schema}, @@ -39,15 +41,19 @@ use super::{ schema::SchemaProvider, }; +use crate::config::ConfigOptions; + const INFORMATION_SCHEMA: &str = "information_schema"; const TABLES: &str = "tables"; const VIEWS: &str = "views"; const COLUMNS: &str = "columns"; +const SETTINGS: &str = "settings"; /// Wraps another [`CatalogProvider`] and adds a "information_schema" /// schema that can introspect on tables in the catalog_list pub(crate) struct CatalogWithInformationSchema { catalog_list: Weak, + config_options: Weak>, /// wrapped provider inner: Arc, } @@ -55,10 +61,12 @@ pub(crate) struct CatalogWithInformationSchema { impl CatalogWithInformationSchema { pub(crate) fn new( catalog_list: Weak, + config_options: Weak>, inner: Arc, ) -> Self { Self { catalog_list, + config_options, inner, } } @@ -79,9 +87,13 @@ impl CatalogProvider for CatalogWithInformationSchema { fn schema(&self, name: &str) -> Option> { if name.eq_ignore_ascii_case(INFORMATION_SCHEMA) { - Weak::upgrade(&self.catalog_list).map(|catalog_list| { - Arc::new(InformationSchemaProvider { catalog_list }) - as Arc + Weak::upgrade(&self.catalog_list).and_then(|catalog_list| { + Weak::upgrade(&self.config_options).map(|config_options| { + Arc::new(InformationSchemaProvider { + catalog_list: catalog_list, + config_options: config_options, + }) as Arc + }) }) } else { self.inner.schema(name) @@ -106,6 +118,7 @@ impl CatalogProvider for CatalogWithInformationSchema { /// table is queried. struct InformationSchemaProvider { catalog_list: Arc, + config_options: Arc>, } impl InformationSchemaProvider { @@ -141,6 +154,12 @@ impl InformationSchemaProvider { COLUMNS, TableType::View, ); + builder.add_table( + &catalog_name, + INFORMATION_SCHEMA, + SETTINGS, + TableType::View, + ); } let mem_table: MemTable = builder.into(); @@ -206,6 +225,19 @@ impl InformationSchemaProvider { Arc::new(mem_table) } + + /// Construct the `information_schema.settings` virtual table + fn make_settings(&self) -> Arc { + let mut builder = InformationSchemaSettingsBuilder::new(); + + for (name, setting) in self.config_options.read().options() { + builder.add_setting(name, setting.to_string()); + } + + let mem_table: MemTable = builder.into(); + + Arc::new(mem_table) + } } impl SchemaProvider for InformationSchemaProvider { @@ -224,6 +256,8 @@ impl SchemaProvider for InformationSchemaProvider { Some(self.make_columns()) } else if name.eq_ignore_ascii_case("views") { Some(self.make_views()) + } else if name.eq_ignore_ascii_case("settings") { + Some(self.make_settings()) } else { None } @@ -579,3 +613,45 @@ impl From for MemTable { MemTable::try_new(schema, vec![vec![batch]]).unwrap() } } + +struct InformationSchemaSettingsBuilder { + names: StringBuilder, + settings: StringBuilder, +} + +impl InformationSchemaSettingsBuilder { + fn new() -> Self { + Self { + names: StringBuilder::new(), + settings: StringBuilder::new(), + } + } + + fn add_setting(&mut self, name: impl AsRef, setting: impl AsRef) { + self.names.append_value(name.as_ref()); + self.settings.append_value(setting.as_ref()); + } +} + +impl From for MemTable { + fn from(value: InformationSchemaSettingsBuilder) -> MemTable { + let schema = Schema::new(vec![ + Field::new("name", DataType::Utf8, false), + Field::new("setting", DataType::Utf8, false), + ]); + + let InformationSchemaSettingsBuilder { + mut names, + mut settings, + } = value; + + let schema = Arc::new(schema); + let batch = RecordBatch::try_new( + schema.clone(), + vec![Arc::new(names.finish()), Arc::new(settings.finish())], + ) + .unwrap(); + + MemTable::try_new(schema, vec![vec![batch]]).unwrap() + } +} diff --git a/datafusion/core/src/execution/context.rs b/datafusion/core/src/execution/context.rs index 64f75dfa24de..e85035bf4420 100644 --- a/datafusion/core/src/execution/context.rs +++ b/datafusion/core/src/execution/context.rs @@ -841,6 +841,7 @@ impl SessionContext { let catalog = if information_schema { Arc::new(CatalogWithInformationSchema::new( Arc::downgrade(&state.catalog_list), + Arc::downgrade(&state.config.config_options), catalog, )) } else { @@ -1130,7 +1131,7 @@ pub struct SessionConfig { /// Should DataFusion parquet reader using the predicate to prune data pub parquet_pruning: bool, /// Configuration options - pub config_options: ConfigOptions, + pub config_options: Arc>, /// Opaque extensions. extensions: AnyMap, } @@ -1147,7 +1148,7 @@ impl Default for SessionConfig { repartition_aggregations: true, repartition_windows: true, parquet_pruning: true, - config_options: ConfigOptions::new(), + config_options: Arc::new(RwLock::new(ConfigOptions::new())), // Assume no extensions by default. extensions: HashMap::with_capacity_and_hasher( 0, @@ -1166,14 +1167,14 @@ impl SessionConfig { /// Create an execution config with config options read from the environment pub fn from_env() -> Self { Self { - config_options: ConfigOptions::from_env(), + config_options: Arc::new(RwLock::new(ConfigOptions::from_env())), ..Default::default() } } /// Set a configuration option - pub fn set(mut self, key: &str, value: ScalarValue) -> Self { - self.config_options.set(key, value); + pub fn set(self, key: &str, value: ScalarValue) -> Self { + self.config_options.write().set(key, value); self } @@ -1252,22 +1253,18 @@ impl SessionConfig { /// Get the currently configured batch size pub fn batch_size(&self) -> usize { self.config_options + .read() .get_u64(OPT_BATCH_SIZE) .try_into() .unwrap() } - /// Get the current configuration options - pub fn config_options(&self) -> &ConfigOptions { - &self.config_options - } - /// Convert configuration options to name-value pairs with values converted to strings. Note /// that this method will eventually be deprecated and replaced by [config_options]. pub fn to_props(&self) -> HashMap { let mut map = HashMap::new(); // copy configs from config_options - for (k, v) in self.config_options.options() { + for (k, v) in self.config_options.read().options() { map.insert(k.to_string(), format!("{}", v)); } map.insert( @@ -1420,6 +1417,7 @@ impl SessionState { let default_catalog: Arc = if config.information_schema { Arc::new(CatalogWithInformationSchema::new( Arc::downgrade(&catalog_list), + Arc::downgrade(&config.config_options), Arc::new(default_catalog), )) } else { @@ -1444,7 +1442,11 @@ impl SessionState { Arc::new(ProjectionPushDown::new()), Arc::new(RewriteDisjunctivePredicate::new()), ]; - if config.config_options.get_bool(OPT_FILTER_NULL_JOIN_KEYS) { + if config + .config_options + .read() + .get_bool(OPT_FILTER_NULL_JOIN_KEYS) + { rules.push(Arc::new(FilterNullJoinKeys::default())); } rules.push(Arc::new(ReduceOuterJoin::new())); @@ -1459,10 +1461,11 @@ impl SessionState { Arc::new(AggregateStatistics::new()), Arc::new(HashBuildProbeOrder::new()), ]; - if config.config_options.get_bool(OPT_COALESCE_BATCHES) { + if config.config_options.read().get_bool(OPT_COALESCE_BATCHES) { physical_optimizers.push(Arc::new(CoalesceBatches::new( config .config_options + .read() .get_u64(OPT_COALESCE_TARGET_BATCH_SIZE) .try_into() .unwrap(), @@ -1566,6 +1569,7 @@ impl SessionState { let mut optimizer_config = OptimizerConfig::new().with_skip_failing_rules( self.config .config_options + .read() .get_bool(OPT_OPTIMIZER_SKIP_FAILED_RULES), ); optimizer_config.query_execution_start_time = diff --git a/datafusion/core/src/physical_plan/planner.rs b/datafusion/core/src/physical_plan/planner.rs index 9f1e488ef524..40109eda2f11 100644 --- a/datafusion/core/src/physical_plan/planner.rs +++ b/datafusion/core/src/physical_plan/planner.rs @@ -1573,6 +1573,7 @@ impl DefaultPhysicalPlanner { if !session_state .config .config_options + .read() .get_bool(OPT_EXPLAIN_PHYSICAL_PLAN_ONLY) { stringified_plans = e.stringified_plans.clone(); @@ -1583,6 +1584,7 @@ impl DefaultPhysicalPlanner { if !session_state .config .config_options + .read() .get_bool(OPT_EXPLAIN_LOGICAL_PLAN_ONLY) { let input = self diff --git a/datafusion/core/tests/sql/information_schema.rs b/datafusion/core/tests/sql/information_schema.rs index 017330e44f33..d9c24bc26e4a 100644 --- a/datafusion/core/tests/sql/information_schema.rs +++ b/datafusion/core/tests/sql/information_schema.rs @@ -56,6 +56,7 @@ async fn information_schema_tables_no_tables() { "| table_catalog | table_schema | table_name | table_type |", "+---------------+--------------------+------------+------------+", "| datafusion | information_schema | columns | VIEW |", + "| datafusion | information_schema | settings | VIEW |", "| datafusion | information_schema | tables | VIEW |", "| datafusion | information_schema | views | VIEW |", "+---------------+--------------------+------------+------------+", @@ -81,6 +82,7 @@ async fn information_schema_tables_tables_default_catalog() { "| table_catalog | table_schema | table_name | table_type |", "+---------------+--------------------+------------+------------+", "| datafusion | information_schema | columns | VIEW |", + "| datafusion | information_schema | settings | VIEW |", "| datafusion | information_schema | tables | VIEW |", "| datafusion | information_schema | views | VIEW |", "| datafusion | public | t | BASE TABLE |", @@ -101,6 +103,7 @@ async fn information_schema_tables_tables_default_catalog() { "| table_catalog | table_schema | table_name | table_type |", "+---------------+--------------------+------------+------------+", "| datafusion | information_schema | columns | VIEW |", + "| datafusion | information_schema | settings | VIEW |", "| datafusion | information_schema | tables | VIEW |", "| datafusion | information_schema | views | VIEW |", "| datafusion | public | t | BASE TABLE |", @@ -146,14 +149,17 @@ async fn information_schema_tables_tables_with_multiple_catalogs() { "| table_catalog | table_schema | table_name | table_type |", "+------------------+--------------------+------------+------------+", "| datafusion | information_schema | columns | VIEW |", + "| datafusion | information_schema | settings | VIEW |", "| datafusion | information_schema | tables | VIEW |", "| datafusion | information_schema | views | VIEW |", "| my_catalog | information_schema | columns | VIEW |", + "| my_catalog | information_schema | settings | VIEW |", "| my_catalog | information_schema | tables | VIEW |", "| my_catalog | information_schema | views | VIEW |", "| my_catalog | my_schema | t1 | BASE TABLE |", "| my_catalog | my_schema | t2 | BASE TABLE |", "| my_other_catalog | information_schema | columns | VIEW |", + "| my_other_catalog | information_schema | settings | VIEW |", "| my_other_catalog | information_schema | tables | VIEW |", "| my_other_catalog | information_schema | views | VIEW |", "| my_other_catalog | my_other_schema | t3 | BASE TABLE |", @@ -210,6 +216,7 @@ async fn information_schema_tables_table_types() { "| table_catalog | table_schema | table_name | table_type |", "+---------------+--------------------+------------+-----------------+", "| datafusion | information_schema | columns | VIEW |", + "| datafusion | information_schema | settings | VIEW |", "| datafusion | information_schema | tables | VIEW |", "| datafusion | information_schema | views | VIEW |", "| datafusion | public | physical | BASE TABLE |", @@ -284,6 +291,7 @@ async fn information_schema_show_tables() { "| table_catalog | table_schema | table_name | table_type |", "+---------------+--------------------+------------+------------+", "| datafusion | information_schema | columns | VIEW |", + "| datafusion | information_schema | settings | VIEW |", "| datafusion | information_schema | tables | VIEW |", "| datafusion | information_schema | views | VIEW |", "| datafusion | public | t | BASE TABLE |", @@ -436,15 +444,40 @@ async fn information_schema_show_table_table_names() { ); } +//#[tokio::test] +//async fn show_unsupported() { +// let ctx = SessionContext::with_config(SessionConfig::new()); +// +// let err = plan_and_collect(&ctx, "SHOW SOMETHING_UNKNOWN") +// .await +// .unwrap_err(); +// +// assert_eq!(err.to_string(), "This feature is not implemented: SHOW SOMETHING_UNKNOWN not implemented. Supported syntax: SHOW "); +//} + +// FIXME +// currently we cannot know whether a variable exists or not while the collect, this will output 0 row instead +// one way to fix this is to generate a ConfigOptions and get options' key to compare +// however config.rs is currently in core lib, could not be used by datafusion_sql due to the dependency cycle #[tokio::test] -async fn show_unsupported() { - let ctx = SessionContext::with_config(SessionConfig::new()); +async fn show_non_existing_variable() { + let ctx = + SessionContext::with_config(SessionConfig::new().with_information_schema(true)); - let err = plan_and_collect(&ctx, "SHOW SOMETHING_UNKNOWN") + let result = plan_and_collect(&ctx, "SHOW SOMETHING_UNKNOWN") .await - .unwrap_err(); + .unwrap(); - assert_eq!(err.to_string(), "This feature is not implemented: SHOW SOMETHING_UNKNOWN not implemented. Supported syntax: SHOW "); + assert_eq!(result[0].num_rows(), 0); +} + +#[tokio::test] +async fn show_unsupported_when_information_schema_off() { + let ctx = SessionContext::with_config(SessionConfig::new()); + + let err = plan_and_collect(&ctx, "SHOW SOMETHING").await.unwrap_err(); + + assert_eq!(err.to_string(), "Error during planning: SHOW [VARIABLE] is not supported unless information_schema is enabled"); } #[tokio::test] @@ -632,3 +665,40 @@ async fn show_external_create_table() { async fn plan_and_collect(ctx: &SessionContext, sql: &str) -> Result> { ctx.sql(sql).await?.collect().await } + +#[tokio::test] +async fn show_variable_in_config_options() { + let ctx = + SessionContext::with_config(SessionConfig::new().with_information_schema(true)); + let sql = "SHOW datafusion.execution.batch_size"; + let results = plan_and_collect(&ctx, sql).await.unwrap(); + + let expected = vec![ + "+---------------------------------+---------+", + "| name | setting |", + "+---------------------------------+---------+", + "| datafusion.execution.batch_size | 8192 |", + "+---------------------------------+---------+", + ]; + + assert_batches_eq!(expected, &results); +} + +#[tokio::test] +async fn show_all() { + let ctx = + SessionContext::with_config(SessionConfig::new().with_information_schema(true)); + let sql = "SHOW ALL"; + + let results = plan_and_collect(&ctx, sql).await.unwrap(); + + let expected_length = ctx + .state + .read() + .config + .config_options + .read() + .options() + .len(); + assert_eq!(expected_length, results[0].num_rows()); +} diff --git a/datafusion/sql/src/planner.rs b/datafusion/sql/src/planner.rs index 5d30b670f82a..514d921b6244 100644 --- a/datafusion/sql/src/planner.rs +++ b/datafusion/sql/src/planner.rs @@ -2378,10 +2378,27 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> { fn show_variable_to_plan(&self, variable: &[Ident]) -> Result { let variable = ObjectName(variable.to_vec()).to_string(); - Err(DataFusionError::NotImplemented(format!( - "SHOW {} not implemented. Supported syntax: SHOW ", - variable - ))) + + if !self.has_table("information_schema", "settings") { + return Err(DataFusionError::Plan( + "SHOW [VARIABLE] is not supported unless information_schema is enabled" + .to_string(), + )); + } + + let query = if variable.to_lowercase() == "all" { + String::from("SELECT name, setting FROM information_schema.settings") + } else { + format!( + "SELECT name, setting FROM information_schema.settings WHERE name = '{}'", + variable + ) + }; + + let mut rewrite = DFParser::parse_sql(&query)?; + assert_eq!(rewrite.len(), 1); + + self.statement_to_plan(rewrite.pop_front().unwrap()) } fn show_columns_to_plan( From 34b0e541637db36d730fb226f2877b3f696cece2 Mon Sep 17 00:00:00 2001 From: Wei-Ting Kuo Date: Tue, 13 Sep 2022 04:16:01 +0800 Subject: [PATCH 2/5] fix test case --- datafusion/core/tests/sql/information_schema.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datafusion/core/tests/sql/information_schema.rs b/datafusion/core/tests/sql/information_schema.rs index d9c24bc26e4a..09eed05bdc05 100644 --- a/datafusion/core/tests/sql/information_schema.rs +++ b/datafusion/core/tests/sql/information_schema.rs @@ -468,7 +468,7 @@ async fn show_non_existing_variable() { .await .unwrap(); - assert_eq!(result[0].num_rows(), 0); + assert_eq!(result.len(), 0); } #[tokio::test] From 8c82064f0f2d81f7dc40fa57e62e617a7455b760 Mon Sep 17 00:00:00 2001 From: Wei-Ting Kuo Date: Tue, 13 Sep 2022 04:42:18 +0800 Subject: [PATCH 3/5] fix comment --- datafusion/core/tests/sql/information_schema.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datafusion/core/tests/sql/information_schema.rs b/datafusion/core/tests/sql/information_schema.rs index 09eed05bdc05..7c61628beeaf 100644 --- a/datafusion/core/tests/sql/information_schema.rs +++ b/datafusion/core/tests/sql/information_schema.rs @@ -456,7 +456,7 @@ async fn information_schema_show_table_table_names() { //} // FIXME -// currently we cannot know whether a variable exists or not while the collect, this will output 0 row instead +// currently we cannot know whether a variable exists, this will output 0 row instead // one way to fix this is to generate a ConfigOptions and get options' key to compare // however config.rs is currently in core lib, could not be used by datafusion_sql due to the dependency cycle #[tokio::test] From 9e7fe41d8d948ad2e792ea900880738be7fdd2a8 Mon Sep 17 00:00:00 2001 From: Wei-Ting Kuo Date: Tue, 13 Sep 2022 05:09:31 +0800 Subject: [PATCH 4/5] fix clippy --- datafusion/core/src/catalog/information_schema.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/datafusion/core/src/catalog/information_schema.rs b/datafusion/core/src/catalog/information_schema.rs index 92450ddbce4a..fa4c7df77324 100644 --- a/datafusion/core/src/catalog/information_schema.rs +++ b/datafusion/core/src/catalog/information_schema.rs @@ -90,8 +90,8 @@ impl CatalogProvider for CatalogWithInformationSchema { Weak::upgrade(&self.catalog_list).and_then(|catalog_list| { Weak::upgrade(&self.config_options).map(|config_options| { Arc::new(InformationSchemaProvider { - catalog_list: catalog_list, - config_options: config_options, + catalog_list, + config_options, }) as Arc }) }) From 0aa105523366ab362c221d33b565f2457fe434de Mon Sep 17 00:00:00 2001 From: Wei-Ting Kuo Date: Wed, 14 Sep 2022 06:22:58 +0800 Subject: [PATCH 5/5] rename settings -> df_settings --- .../core/src/catalog/information_schema.rs | 24 ++-- .../core/tests/sql/information_schema.rs | 133 +++++++++--------- datafusion/sql/src/planner.rs | 6 +- 3 files changed, 82 insertions(+), 81 deletions(-) diff --git a/datafusion/core/src/catalog/information_schema.rs b/datafusion/core/src/catalog/information_schema.rs index fa4c7df77324..eca399e27093 100644 --- a/datafusion/core/src/catalog/information_schema.rs +++ b/datafusion/core/src/catalog/information_schema.rs @@ -47,7 +47,7 @@ const INFORMATION_SCHEMA: &str = "information_schema"; const TABLES: &str = "tables"; const VIEWS: &str = "views"; const COLUMNS: &str = "columns"; -const SETTINGS: &str = "settings"; +const DF_SETTINGS: &str = "df_settings"; /// Wraps another [`CatalogProvider`] and adds a "information_schema" /// schema that can introspect on tables in the catalog_list @@ -157,7 +157,7 @@ impl InformationSchemaProvider { builder.add_table( &catalog_name, INFORMATION_SCHEMA, - SETTINGS, + DF_SETTINGS, TableType::View, ); } @@ -226,9 +226,9 @@ impl InformationSchemaProvider { Arc::new(mem_table) } - /// Construct the `information_schema.settings` virtual table - fn make_settings(&self) -> Arc { - let mut builder = InformationSchemaSettingsBuilder::new(); + /// Construct the `information_schema.df_settings` virtual table + fn make_df_settings(&self) -> Arc { + let mut builder = InformationSchemaDfSettingsBuilder::new(); for (name, setting) in self.config_options.read().options() { builder.add_setting(name, setting.to_string()); @@ -256,8 +256,8 @@ impl SchemaProvider for InformationSchemaProvider { Some(self.make_columns()) } else if name.eq_ignore_ascii_case("views") { Some(self.make_views()) - } else if name.eq_ignore_ascii_case("settings") { - Some(self.make_settings()) + } else if name.eq_ignore_ascii_case("df_settings") { + Some(self.make_df_settings()) } else { None } @@ -614,12 +614,12 @@ impl From for MemTable { } } -struct InformationSchemaSettingsBuilder { +struct InformationSchemaDfSettingsBuilder { names: StringBuilder, settings: StringBuilder, } -impl InformationSchemaSettingsBuilder { +impl InformationSchemaDfSettingsBuilder { fn new() -> Self { Self { names: StringBuilder::new(), @@ -633,14 +633,14 @@ impl InformationSchemaSettingsBuilder { } } -impl From for MemTable { - fn from(value: InformationSchemaSettingsBuilder) -> MemTable { +impl From for MemTable { + fn from(value: InformationSchemaDfSettingsBuilder) -> MemTable { let schema = Schema::new(vec![ Field::new("name", DataType::Utf8, false), Field::new("setting", DataType::Utf8, false), ]); - let InformationSchemaSettingsBuilder { + let InformationSchemaDfSettingsBuilder { mut names, mut settings, } = value; diff --git a/datafusion/core/tests/sql/information_schema.rs b/datafusion/core/tests/sql/information_schema.rs index 7c61628beeaf..c9a5c9aa9cd5 100644 --- a/datafusion/core/tests/sql/information_schema.rs +++ b/datafusion/core/tests/sql/information_schema.rs @@ -52,14 +52,14 @@ async fn information_schema_tables_no_tables() { .unwrap(); let expected = vec![ - "+---------------+--------------------+------------+------------+", - "| table_catalog | table_schema | table_name | table_type |", - "+---------------+--------------------+------------+------------+", - "| datafusion | information_schema | columns | VIEW |", - "| datafusion | information_schema | settings | VIEW |", - "| datafusion | information_schema | tables | VIEW |", - "| datafusion | information_schema | views | VIEW |", - "+---------------+--------------------+------------+------------+", + "+---------------+--------------------+-------------+------------+", + "| table_catalog | table_schema | table_name | table_type |", + "+---------------+--------------------+-------------+------------+", + "| datafusion | information_schema | columns | VIEW |", + "| datafusion | information_schema | df_settings | VIEW |", + "| datafusion | information_schema | tables | VIEW |", + "| datafusion | information_schema | views | VIEW |", + "+---------------+--------------------+-------------+------------+", ]; assert_batches_sorted_eq!(expected, &result); } @@ -78,15 +78,15 @@ async fn information_schema_tables_tables_default_catalog() { .unwrap(); let expected = vec![ - "+---------------+--------------------+------------+------------+", - "| table_catalog | table_schema | table_name | table_type |", - "+---------------+--------------------+------------+------------+", - "| datafusion | information_schema | columns | VIEW |", - "| datafusion | information_schema | settings | VIEW |", - "| datafusion | information_schema | tables | VIEW |", - "| datafusion | information_schema | views | VIEW |", - "| datafusion | public | t | BASE TABLE |", - "+---------------+--------------------+------------+------------+", + "+---------------+--------------------+-------------+------------+", + "| table_catalog | table_schema | table_name | table_type |", + "+---------------+--------------------+-------------+------------+", + "| datafusion | information_schema | columns | VIEW |", + "| datafusion | information_schema | df_settings | VIEW |", + "| datafusion | information_schema | tables | VIEW |", + "| datafusion | information_schema | views | VIEW |", + "| datafusion | public | t | BASE TABLE |", + "+---------------+--------------------+-------------+------------+", ]; assert_batches_sorted_eq!(expected, &result); @@ -99,16 +99,16 @@ async fn information_schema_tables_tables_default_catalog() { .unwrap(); let expected = vec![ - "+---------------+--------------------+------------+------------+", - "| table_catalog | table_schema | table_name | table_type |", - "+---------------+--------------------+------------+------------+", - "| datafusion | information_schema | columns | VIEW |", - "| datafusion | information_schema | settings | VIEW |", - "| datafusion | information_schema | tables | VIEW |", - "| datafusion | information_schema | views | VIEW |", - "| datafusion | public | t | BASE TABLE |", - "| datafusion | public | t2 | BASE TABLE |", - "+---------------+--------------------+------------+------------+", + "+---------------+--------------------+-------------+------------+", + "| table_catalog | table_schema | table_name | table_type |", + "+---------------+--------------------+-------------+------------+", + "| datafusion | information_schema | columns | VIEW |", + "| datafusion | information_schema | df_settings | VIEW |", + "| datafusion | information_schema | tables | VIEW |", + "| datafusion | information_schema | views | VIEW |", + "| datafusion | public | t | BASE TABLE |", + "| datafusion | public | t2 | BASE TABLE |", + "+---------------+--------------------+-------------+------------+", ]; assert_batches_sorted_eq!(expected, &result); } @@ -145,25 +145,25 @@ async fn information_schema_tables_tables_with_multiple_catalogs() { .unwrap(); let expected = vec![ - "+------------------+--------------------+------------+------------+", - "| table_catalog | table_schema | table_name | table_type |", - "+------------------+--------------------+------------+------------+", - "| datafusion | information_schema | columns | VIEW |", - "| datafusion | information_schema | settings | VIEW |", - "| datafusion | information_schema | tables | VIEW |", - "| datafusion | information_schema | views | VIEW |", - "| my_catalog | information_schema | columns | VIEW |", - "| my_catalog | information_schema | settings | VIEW |", - "| my_catalog | information_schema | tables | VIEW |", - "| my_catalog | information_schema | views | VIEW |", - "| my_catalog | my_schema | t1 | BASE TABLE |", - "| my_catalog | my_schema | t2 | BASE TABLE |", - "| my_other_catalog | information_schema | columns | VIEW |", - "| my_other_catalog | information_schema | settings | VIEW |", - "| my_other_catalog | information_schema | tables | VIEW |", - "| my_other_catalog | information_schema | views | VIEW |", - "| my_other_catalog | my_other_schema | t3 | BASE TABLE |", - "+------------------+--------------------+------------+------------+", + "+------------------+--------------------+-------------+------------+", + "| table_catalog | table_schema | table_name | table_type |", + "+------------------+--------------------+-------------+------------+", + "| datafusion | information_schema | columns | VIEW |", + "| datafusion | information_schema | df_settings | VIEW |", + "| datafusion | information_schema | tables | VIEW |", + "| datafusion | information_schema | views | VIEW |", + "| my_catalog | information_schema | columns | VIEW |", + "| my_catalog | information_schema | df_settings | VIEW |", + "| my_catalog | information_schema | tables | VIEW |", + "| my_catalog | information_schema | views | VIEW |", + "| my_catalog | my_schema | t1 | BASE TABLE |", + "| my_catalog | my_schema | t2 | BASE TABLE |", + "| my_other_catalog | information_schema | columns | VIEW |", + "| my_other_catalog | information_schema | df_settings | VIEW |", + "| my_other_catalog | information_schema | tables | VIEW |", + "| my_other_catalog | information_schema | views | VIEW |", + "| my_other_catalog | my_other_schema | t3 | BASE TABLE |", + "+------------------+--------------------+-------------+------------+", ]; assert_batches_sorted_eq!(expected, &result); } @@ -212,17 +212,17 @@ async fn information_schema_tables_table_types() { .unwrap(); let expected = vec![ - "+---------------+--------------------+------------+-----------------+", - "| table_catalog | table_schema | table_name | table_type |", - "+---------------+--------------------+------------+-----------------+", - "| datafusion | information_schema | columns | VIEW |", - "| datafusion | information_schema | settings | VIEW |", - "| datafusion | information_schema | tables | VIEW |", - "| datafusion | information_schema | views | VIEW |", - "| datafusion | public | physical | BASE TABLE |", - "| datafusion | public | query | VIEW |", - "| datafusion | public | temp | LOCAL TEMPORARY |", - "+---------------+--------------------+------------+-----------------+", + "+---------------+--------------------+-------------+-----------------+", + "| table_catalog | table_schema | table_name | table_type |", + "+---------------+--------------------+-------------+-----------------+", + "| datafusion | information_schema | columns | VIEW |", + "| datafusion | information_schema | df_settings | VIEW |", + "| datafusion | information_schema | tables | VIEW |", + "| datafusion | information_schema | views | VIEW |", + "| datafusion | public | physical | BASE TABLE |", + "| datafusion | public | query | VIEW |", + "| datafusion | public | temp | LOCAL TEMPORARY |", + "+---------------+--------------------+-------------+-----------------+", ]; assert_batches_sorted_eq!(expected, &result); } @@ -287,15 +287,15 @@ async fn information_schema_show_tables() { let result = plan_and_collect(&ctx, "SHOW TABLES").await.unwrap(); let expected = vec![ - "+---------------+--------------------+------------+------------+", - "| table_catalog | table_schema | table_name | table_type |", - "+---------------+--------------------+------------+------------+", - "| datafusion | information_schema | columns | VIEW |", - "| datafusion | information_schema | settings | VIEW |", - "| datafusion | information_schema | tables | VIEW |", - "| datafusion | information_schema | views | VIEW |", - "| datafusion | public | t | BASE TABLE |", - "+---------------+--------------------+------------+------------+", + "+---------------+--------------------+-------------+------------+", + "| table_catalog | table_schema | table_name | table_type |", + "+---------------+--------------------+-------------+------------+", + "| datafusion | information_schema | columns | VIEW |", + "| datafusion | information_schema | df_settings | VIEW |", + "| datafusion | information_schema | tables | VIEW |", + "| datafusion | information_schema | views | VIEW |", + "| datafusion | public | t | BASE TABLE |", + "+---------------+--------------------+-------------+------------+", ]; assert_batches_sorted_eq!(expected, &result); @@ -444,6 +444,7 @@ async fn information_schema_show_table_table_names() { ); } +// FIXME once we support raise error while show non-existing variable, we could add this back //#[tokio::test] //async fn show_unsupported() { // let ctx = SessionContext::with_config(SessionConfig::new()); diff --git a/datafusion/sql/src/planner.rs b/datafusion/sql/src/planner.rs index 514d921b6244..0338d713a3c6 100644 --- a/datafusion/sql/src/planner.rs +++ b/datafusion/sql/src/planner.rs @@ -2379,7 +2379,7 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> { fn show_variable_to_plan(&self, variable: &[Ident]) -> Result { let variable = ObjectName(variable.to_vec()).to_string(); - if !self.has_table("information_schema", "settings") { + if !self.has_table("information_schema", "df_settings") { return Err(DataFusionError::Plan( "SHOW [VARIABLE] is not supported unless information_schema is enabled" .to_string(), @@ -2387,10 +2387,10 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> { } let query = if variable.to_lowercase() == "all" { - String::from("SELECT name, setting FROM information_schema.settings") + String::from("SELECT name, setting FROM information_schema.df_settings") } else { format!( - "SELECT name, setting FROM information_schema.settings WHERE name = '{}'", + "SELECT name, setting FROM information_schema.df_settings WHERE name = '{}'", variable ) };