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 ed1de63 Move `information_schema` tests out of execution/context.rs
to `sql_integration` tests (#1684)
ed1de63 is described below
commit ed1de63aea89ba3b025ef431a60bff68adce1bcd
Author: Andrew Lamb <[email protected]>
AuthorDate: Fri Jan 28 09:47:57 2022 -0500
Move `information_schema` tests out of execution/context.rs to
`sql_integration` tests (#1684)
* Move tests from context.rs to information_schema.rs
* Fix up tests to compile
---
datafusion/src/execution/context.rs | 477 +--------------------------
datafusion/tests/sql/information_schema.rs | 502 +++++++++++++++++++++++++++++
datafusion/tests/sql/mod.rs | 17 +
3 files changed, 522 insertions(+), 474 deletions(-)
diff --git a/datafusion/src/execution/context.rs
b/datafusion/src/execution/context.rs
index 61cbf3a..9cc54df 100644
--- a/datafusion/src/execution/context.rs
+++ b/datafusion/src/execution/context.rs
@@ -1277,14 +1277,13 @@ mod tests {
logical_plan::{col, create_udf, sum, Expr},
};
use crate::{
- datasource::{empty::EmptyTable, MemTable, TableType},
+ datasource::{empty::EmptyTable, MemTable},
logical_plan::create_udaf,
physical_plan::expressions::AvgAccumulator,
};
use arrow::array::{
- Array, ArrayRef, BinaryArray, DictionaryArray, Float32Array,
Float64Array,
- Int16Array, Int32Array, Int64Array, Int8Array, LargeBinaryArray,
- LargeStringArray, StringArray, TimestampNanosecondArray, UInt16Array,
+ Array, ArrayRef, DictionaryArray, Float32Array, Float64Array,
Int16Array,
+ Int32Array, Int64Array, Int8Array, LargeStringArray, StringArray,
UInt16Array,
UInt32Array, UInt64Array, UInt8Array,
};
use arrow::compute::add;
@@ -3552,476 +3551,6 @@ mod tests {
}
#[tokio::test]
- async fn information_schema_tables_not_exist_by_default() {
- let mut ctx = ExecutionContext::new();
-
- let err = plan_and_collect(&mut ctx, "SELECT * from
information_schema.tables")
- .await
- .unwrap_err();
- assert_eq!(
- err.to_string(),
- "Error during planning: Table or CTE with name
'information_schema.tables' not found"
- );
- }
-
- #[tokio::test]
- async fn information_schema_tables_no_tables() {
- let mut ctx = ExecutionContext::with_config(
- ExecutionConfig::new().with_information_schema(true),
- );
-
- let result =
- plan_and_collect(&mut ctx, "SELECT * from
information_schema.tables")
- .await
- .unwrap();
-
- let expected = vec![
- "+---------------+--------------------+------------+------------+",
- "| table_catalog | table_schema | table_name | table_type |",
- "+---------------+--------------------+------------+------------+",
- "| datafusion | information_schema | columns | VIEW |",
- "| datafusion | information_schema | tables | VIEW |",
- "+---------------+--------------------+------------+------------+",
- ];
- assert_batches_sorted_eq!(expected, &result);
- }
-
- #[tokio::test]
- async fn information_schema_tables_tables_default_catalog() {
- let mut ctx = ExecutionContext::with_config(
- ExecutionConfig::new().with_information_schema(true),
- );
-
- // Now, register an empty table
- ctx.register_table("t", test::table_with_sequence(1, 1).unwrap())
- .unwrap();
-
- let result =
- plan_and_collect(&mut ctx, "SELECT * from
information_schema.tables")
- .await
- .unwrap();
-
- let expected = vec![
- "+---------------+--------------------+------------+------------+",
- "| table_catalog | table_schema | table_name | table_type |",
- "+---------------+--------------------+------------+------------+",
- "| datafusion | information_schema | tables | VIEW |",
- "| datafusion | information_schema | columns | VIEW |",
- "| datafusion | public | t | BASE TABLE |",
- "+---------------+--------------------+------------+------------+",
- ];
- assert_batches_sorted_eq!(expected, &result);
-
- // Newly added tables should appear
- ctx.register_table("t2", test::table_with_sequence(1, 1).unwrap())
- .unwrap();
-
- let result =
- plan_and_collect(&mut ctx, "SELECT * from
information_schema.tables")
- .await
- .unwrap();
-
- let expected = vec![
- "+---------------+--------------------+------------+------------+",
- "| table_catalog | table_schema | table_name | table_type |",
- "+---------------+--------------------+------------+------------+",
- "| datafusion | information_schema | columns | VIEW |",
- "| datafusion | information_schema | tables | VIEW |",
- "| datafusion | public | t | BASE TABLE |",
- "| datafusion | public | t2 | BASE TABLE |",
- "+---------------+--------------------+------------+------------+",
- ];
- assert_batches_sorted_eq!(expected, &result);
- }
-
- #[tokio::test]
- async fn information_schema_tables_tables_with_multiple_catalogs() {
- let mut ctx = ExecutionContext::with_config(
- ExecutionConfig::new().with_information_schema(true),
- );
- let catalog = MemoryCatalogProvider::new();
- let schema = MemorySchemaProvider::new();
- schema
- .register_table("t1".to_owned(), test::table_with_sequence(1,
1).unwrap())
- .unwrap();
- schema
- .register_table("t2".to_owned(), test::table_with_sequence(1,
1).unwrap())
- .unwrap();
- catalog.register_schema("my_schema", Arc::new(schema));
- ctx.register_catalog("my_catalog", Arc::new(catalog));
-
- let catalog = MemoryCatalogProvider::new();
- let schema = MemorySchemaProvider::new();
- schema
- .register_table("t3".to_owned(), test::table_with_sequence(1,
1).unwrap())
- .unwrap();
- catalog.register_schema("my_other_schema", Arc::new(schema));
- ctx.register_catalog("my_other_catalog", Arc::new(catalog));
-
- let result =
- plan_and_collect(&mut ctx, "SELECT * from
information_schema.tables")
- .await
- .unwrap();
-
- let expected = vec![
-
"+------------------+--------------------+------------+------------+",
- "| table_catalog | table_schema | table_name | table_type
|",
-
"+------------------+--------------------+------------+------------+",
- "| datafusion | information_schema | columns | VIEW
|",
- "| datafusion | information_schema | tables | VIEW
|",
- "| my_catalog | information_schema | columns | VIEW
|",
- "| my_catalog | information_schema | tables | 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 | tables | VIEW
|",
- "| my_other_catalog | my_other_schema | t3 | BASE TABLE
|",
-
"+------------------+--------------------+------------+------------+",
- ];
- assert_batches_sorted_eq!(expected, &result);
- }
-
- #[tokio::test]
- async fn information_schema_tables_table_types() {
- struct TestTable(TableType);
-
- #[async_trait]
- impl TableProvider for TestTable {
- fn as_any(&self) -> &dyn std::any::Any {
- self
- }
-
- fn table_type(&self) -> TableType {
- self.0
- }
-
- fn schema(&self) -> SchemaRef {
- unimplemented!()
- }
-
- async fn scan(
- &self,
- _: &Option<Vec<usize>>,
- _: &[Expr],
- _: Option<usize>,
- ) -> Result<Arc<dyn ExecutionPlan>> {
- unimplemented!()
- }
- }
-
- let mut ctx = ExecutionContext::with_config(
- ExecutionConfig::new().with_information_schema(true),
- );
-
- ctx.register_table("physical", Arc::new(TestTable(TableType::Base)))
- .unwrap();
- ctx.register_table("query", Arc::new(TestTable(TableType::View)))
- .unwrap();
- ctx.register_table("temp", Arc::new(TestTable(TableType::Temporary)))
- .unwrap();
-
- let result =
- plan_and_collect(&mut ctx, "SELECT * from
information_schema.tables")
- .await
- .unwrap();
-
- let expected = vec![
-
"+---------------+--------------------+------------+-----------------+",
- "| table_catalog | table_schema | table_name | table_type
|",
-
"+---------------+--------------------+------------+-----------------+",
- "| datafusion | information_schema | tables | VIEW
|",
- "| datafusion | information_schema | columns | VIEW
|",
- "| datafusion | public | physical | BASE TABLE
|",
- "| datafusion | public | query | VIEW
|",
- "| datafusion | public | temp | LOCAL
TEMPORARY |",
-
"+---------------+--------------------+------------+-----------------+",
- ];
- assert_batches_sorted_eq!(expected, &result);
- }
-
- #[tokio::test]
- async fn information_schema_show_tables_no_information_schema() {
- let mut ctx = ExecutionContext::with_config(ExecutionConfig::new());
-
- ctx.register_table("t", test::table_with_sequence(1, 1).unwrap())
- .unwrap();
-
- // use show tables alias
- let err = plan_and_collect(&mut ctx, "SHOW TABLES").await.unwrap_err();
-
- assert_eq!(err.to_string(), "Error during planning: SHOW TABLES is not
supported unless information_schema is enabled");
- }
-
- #[tokio::test]
- async fn information_schema_show_tables() {
- let mut ctx = ExecutionContext::with_config(
- ExecutionConfig::new().with_information_schema(true),
- );
-
- ctx.register_table("t", test::table_with_sequence(1, 1).unwrap())
- .unwrap();
-
- // use show tables alias
- let result = plan_and_collect(&mut ctx, "SHOW TABLES").await.unwrap();
-
- let expected = vec![
- "+---------------+--------------------+------------+------------+",
- "| table_catalog | table_schema | table_name | table_type |",
- "+---------------+--------------------+------------+------------+",
- "| datafusion | information_schema | columns | VIEW |",
- "| datafusion | information_schema | tables | VIEW |",
- "| datafusion | public | t | BASE TABLE |",
- "+---------------+--------------------+------------+------------+",
- ];
- assert_batches_sorted_eq!(expected, &result);
-
- let result = plan_and_collect(&mut ctx, "SHOW tables").await.unwrap();
-
- assert_batches_sorted_eq!(expected, &result);
- }
-
- #[tokio::test]
- async fn information_schema_show_columns_no_information_schema() {
- let mut ctx = ExecutionContext::with_config(ExecutionConfig::new());
-
- ctx.register_table("t", test::table_with_sequence(1, 1).unwrap())
- .unwrap();
-
- let err = plan_and_collect(&mut ctx, "SHOW COLUMNS FROM t")
- .await
- .unwrap_err();
-
- assert_eq!(err.to_string(), "Error during planning: SHOW COLUMNS is
not supported unless information_schema is enabled");
- }
-
- #[tokio::test]
- async fn information_schema_show_columns_like_where() {
- let mut ctx = ExecutionContext::with_config(ExecutionConfig::new());
-
- ctx.register_table("t", test::table_with_sequence(1, 1).unwrap())
- .unwrap();
-
- let expected =
- "Error during planning: SHOW COLUMNS with WHERE or LIKE is not
supported";
-
- let err = plan_and_collect(&mut ctx, "SHOW COLUMNS FROM t LIKE 'f'")
- .await
- .unwrap_err();
- assert_eq!(err.to_string(), expected);
-
- let err =
- plan_and_collect(&mut ctx, "SHOW COLUMNS FROM t WHERE column_name
= 'bar'")
- .await
- .unwrap_err();
- assert_eq!(err.to_string(), expected);
- }
-
- #[tokio::test]
- async fn information_schema_show_columns() {
- let mut ctx = ExecutionContext::with_config(
- ExecutionConfig::new().with_information_schema(true),
- );
-
- ctx.register_table("t", test::table_with_sequence(1, 1).unwrap())
- .unwrap();
-
- let result = plan_and_collect(&mut ctx, "SHOW COLUMNS FROM t")
- .await
- .unwrap();
-
- let expected = vec![
-
"+---------------+--------------+------------+-------------+-----------+-------------+",
- "| table_catalog | table_schema | table_name | column_name |
data_type | is_nullable |",
-
"+---------------+--------------+------------+-------------+-----------+-------------+",
- "| datafusion | public | t | i | Int32
| YES |",
-
"+---------------+--------------+------------+-------------+-----------+-------------+",
- ];
- assert_batches_sorted_eq!(expected, &result);
-
- let result = plan_and_collect(&mut ctx, "SHOW columns from t")
- .await
- .unwrap();
- assert_batches_sorted_eq!(expected, &result);
-
- // This isn't ideal but it is consistent behavior for `SELECT * from T`
- let err = plan_and_collect(&mut ctx, "SHOW columns from T")
- .await
- .unwrap_err();
- assert_eq!(
- err.to_string(),
- "Error during planning: Unknown relation for SHOW COLUMNS: T"
- );
- }
-
- // test errors with WHERE and LIKE
- #[tokio::test]
- async fn information_schema_show_columns_full_extended() {
- let mut ctx = ExecutionContext::with_config(
- ExecutionConfig::new().with_information_schema(true),
- );
-
- ctx.register_table("t", test::table_with_sequence(1, 1).unwrap())
- .unwrap();
-
- let result = plan_and_collect(&mut ctx, "SHOW FULL COLUMNS FROM t")
- .await
- .unwrap();
- let expected = vec![
-
"+---------------+--------------+------------+-------------+------------------+----------------+-------------+-----------+--------------------------+------------------------+-------------------+-------------------------+---------------+--------------------+---------------+",
- "| table_catalog | table_schema | table_name | column_name |
ordinal_position | column_default | is_nullable | data_type |
character_maximum_length | character_octet_length | numeric_precision |
numeric_precision_radix | numeric_scale | datetime_precision | interval_type |",
-
"+---------------+--------------+------------+-------------+------------------+----------------+-------------+-----------+--------------------------+------------------------+-------------------+-------------------------+---------------+--------------------+---------------+",
- "| datafusion | public | t | i | 0
| | YES | Int32 |
| | 32 | 2 |
| | |",
-
"+---------------+--------------+------------+-------------+------------------+----------------+-------------+-----------+--------------------------+------------------------+-------------------+-------------------------+---------------+--------------------+---------------+",
- ];
- assert_batches_sorted_eq!(expected, &result);
-
- let result = plan_and_collect(&mut ctx, "SHOW EXTENDED COLUMNS FROM t")
- .await
- .unwrap();
- assert_batches_sorted_eq!(expected, &result);
- }
-
- #[tokio::test]
- async fn information_schema_show_table_table_names() {
- let mut ctx = ExecutionContext::with_config(
- ExecutionConfig::new().with_information_schema(true),
- );
-
- ctx.register_table("t", test::table_with_sequence(1, 1).unwrap())
- .unwrap();
-
- let result = plan_and_collect(&mut ctx, "SHOW COLUMNS FROM public.t")
- .await
- .unwrap();
-
- let expected = vec![
-
"+---------------+--------------+------------+-------------+-----------+-------------+",
- "| table_catalog | table_schema | table_name | column_name |
data_type | is_nullable |",
-
"+---------------+--------------+------------+-------------+-----------+-------------+",
- "| datafusion | public | t | i | Int32
| YES |",
-
"+---------------+--------------+------------+-------------+-----------+-------------+",
- ];
- assert_batches_sorted_eq!(expected, &result);
-
- let result = plan_and_collect(&mut ctx, "SHOW columns from
datafusion.public.t")
- .await
- .unwrap();
- assert_batches_sorted_eq!(expected, &result);
-
- let err = plan_and_collect(&mut ctx, "SHOW columns from t2")
- .await
- .unwrap_err();
- assert_eq!(
- err.to_string(),
- "Error during planning: Unknown relation for SHOW COLUMNS: t2"
- );
-
- let err = plan_and_collect(&mut ctx, "SHOW columns from
datafusion.public.t2")
- .await
- .unwrap_err();
- assert_eq!(err.to_string(), "Error during planning: Unknown relation
for SHOW COLUMNS: datafusion.public.t2");
- }
-
- #[tokio::test]
- async fn show_unsupported() {
- let mut ctx = ExecutionContext::with_config(ExecutionConfig::new());
-
- let err = plan_and_collect(&mut 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 <TABLES>");
- }
-
- #[tokio::test]
- async fn information_schema_columns_not_exist_by_default() {
- let mut ctx = ExecutionContext::new();
-
- let err = plan_and_collect(&mut ctx, "SELECT * from
information_schema.columns")
- .await
- .unwrap_err();
- assert_eq!(
- err.to_string(),
- "Error during planning: Table or CTE with name
'information_schema.columns' not found"
- );
- }
-
- fn table_with_many_types() -> Arc<dyn TableProvider> {
- let schema = Schema::new(vec![
- Field::new("int32_col", DataType::Int32, false),
- Field::new("float64_col", DataType::Float64, true),
- Field::new("utf8_col", DataType::Utf8, true),
- Field::new("large_utf8_col", DataType::LargeUtf8, false),
- Field::new("binary_col", DataType::Binary, false),
- Field::new("large_binary_col", DataType::LargeBinary, false),
- Field::new(
- "timestamp_nanos",
- DataType::Timestamp(TimeUnit::Nanosecond, None),
- false,
- ),
- ]);
-
- let batch = RecordBatch::try_new(
- Arc::new(schema.clone()),
- vec![
- Arc::new(Int32Array::from_slice(&[1])),
- Arc::new(Float64Array::from_slice(&[1.0])),
- Arc::new(StringArray::from(vec![Some("foo")])),
- Arc::new(LargeStringArray::from(vec![Some("bar")])),
- Arc::new(BinaryArray::from_slice(&[b"foo" as &[u8]])),
- Arc::new(LargeBinaryArray::from_slice(&[b"foo" as &[u8]])),
- Arc::new(TimestampNanosecondArray::from_opt_vec(
- vec![Some(123)],
- None,
- )),
- ],
- )
- .unwrap();
- let provider = MemTable::try_new(Arc::new(schema),
vec![vec![batch]]).unwrap();
- Arc::new(provider)
- }
-
- #[tokio::test]
- async fn information_schema_columns() {
- let mut ctx = ExecutionContext::with_config(
- ExecutionConfig::new().with_information_schema(true),
- );
- let catalog = MemoryCatalogProvider::new();
- let schema = MemorySchemaProvider::new();
-
- schema
- .register_table("t1".to_owned(), test::table_with_sequence(1,
1).unwrap())
- .unwrap();
-
- schema
- .register_table("t2".to_owned(), table_with_many_types())
- .unwrap();
- catalog.register_schema("my_schema", Arc::new(schema));
- ctx.register_catalog("my_catalog", Arc::new(catalog));
-
- let result =
- plan_and_collect(&mut ctx, "SELECT * from
information_schema.columns")
- .await
- .unwrap();
-
- let expected = vec![
-
"+---------------+--------------+------------+------------------+------------------+----------------+-------------+-----------------------------+--------------------------+------------------------+-------------------+-------------------------+---------------+--------------------+---------------+",
- "| table_catalog | table_schema | table_name | column_name |
ordinal_position | column_default | is_nullable | data_type |
character_maximum_length | character_octet_length | numeric_precision |
numeric_precision_radix | numeric_scale | datetime_precision | interval_type |",
-
"+---------------+--------------+------------+------------------+------------------+----------------+-------------+-----------------------------+--------------------------+------------------------+-------------------+-------------------------+---------------+--------------------+---------------+",
- "| my_catalog | my_schema | t1 | i |
0 | | YES | Int32 |
| | 32 | 2
| | | |",
- "| my_catalog | my_schema | t2 | binary_col |
4 | | NO | Binary |
| 2147483647 | |
| | | |",
- "| my_catalog | my_schema | t2 | float64_col |
1 | | YES | Float64 |
| | 24 | 2
| | | |",
- "| my_catalog | my_schema | t2 | int32_col |
0 | | NO | Int32 |
| | 32 | 2
| | | |",
- "| my_catalog | my_schema | t2 | large_binary_col |
5 | | NO | LargeBinary |
| 9223372036854775807 | |
| | | |",
- "| my_catalog | my_schema | t2 | large_utf8_col |
3 | | NO | LargeUtf8 |
| 9223372036854775807 | |
| | | |",
- "| my_catalog | my_schema | t2 | timestamp_nanos |
6 | | NO | Timestamp(Nanosecond, None) |
| | |
| | | |",
- "| my_catalog | my_schema | t2 | utf8_col |
2 | | YES | Utf8 |
| 2147483647 | |
| | | |",
-
"+---------------+--------------+------------+------------------+------------------+----------------+-------------+-----------------------------+--------------------------+------------------------+-------------------+-------------------------+---------------+--------------------+---------------+",
- ];
- assert_batches_sorted_eq!(expected, &result);
- }
-
- #[tokio::test]
async fn disabled_default_catalog_and_schema() -> Result<()> {
let mut ctx = ExecutionContext::with_config(
ExecutionConfig::new().create_default_catalog_and_schema(false),
diff --git a/datafusion/tests/sql/information_schema.rs
b/datafusion/tests/sql/information_schema.rs
new file mode 100644
index 0000000..d93f0d7
--- /dev/null
+++ b/datafusion/tests/sql/information_schema.rs
@@ -0,0 +1,502 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use async_trait::async_trait;
+use datafusion::{
+ catalog::{
+ catalog::MemoryCatalogProvider,
+ schema::{MemorySchemaProvider, SchemaProvider},
+ },
+ datasource::{TableProvider, TableType},
+ logical_plan::Expr,
+};
+
+use super::*;
+
+#[tokio::test]
+async fn information_schema_tables_not_exist_by_default() {
+ let mut ctx = ExecutionContext::new();
+
+ let err = plan_and_collect(&mut ctx, "SELECT * from
information_schema.tables")
+ .await
+ .unwrap_err();
+ assert_eq!(
+ err.to_string(),
+ "Error during planning: Table or CTE with name
'information_schema.tables' not found"
+ );
+}
+
+#[tokio::test]
+async fn information_schema_tables_no_tables() {
+ let mut ctx = ExecutionContext::with_config(
+ ExecutionConfig::new().with_information_schema(true),
+ );
+
+ let result = plan_and_collect(&mut ctx, "SELECT * from
information_schema.tables")
+ .await
+ .unwrap();
+
+ let expected = vec![
+ "+---------------+--------------------+------------+------------+",
+ "| table_catalog | table_schema | table_name | table_type |",
+ "+---------------+--------------------+------------+------------+",
+ "| datafusion | information_schema | columns | VIEW |",
+ "| datafusion | information_schema | tables | VIEW |",
+ "+---------------+--------------------+------------+------------+",
+ ];
+ assert_batches_sorted_eq!(expected, &result);
+}
+
+#[tokio::test]
+async fn information_schema_tables_tables_default_catalog() {
+ let mut ctx = ExecutionContext::with_config(
+ ExecutionConfig::new().with_information_schema(true),
+ );
+
+ // Now, register an empty table
+ ctx.register_table("t", table_with_sequence(1, 1).unwrap())
+ .unwrap();
+
+ let result = plan_and_collect(&mut ctx, "SELECT * from
information_schema.tables")
+ .await
+ .unwrap();
+
+ let expected = vec![
+ "+---------------+--------------------+------------+------------+",
+ "| table_catalog | table_schema | table_name | table_type |",
+ "+---------------+--------------------+------------+------------+",
+ "| datafusion | information_schema | tables | VIEW |",
+ "| datafusion | information_schema | columns | VIEW |",
+ "| datafusion | public | t | BASE TABLE |",
+ "+---------------+--------------------+------------+------------+",
+ ];
+ assert_batches_sorted_eq!(expected, &result);
+
+ // Newly added tables should appear
+ ctx.register_table("t2", table_with_sequence(1, 1).unwrap())
+ .unwrap();
+
+ let result = plan_and_collect(&mut ctx, "SELECT * from
information_schema.tables")
+ .await
+ .unwrap();
+
+ let expected = vec![
+ "+---------------+--------------------+------------+------------+",
+ "| table_catalog | table_schema | table_name | table_type |",
+ "+---------------+--------------------+------------+------------+",
+ "| datafusion | information_schema | columns | VIEW |",
+ "| datafusion | information_schema | tables | VIEW |",
+ "| datafusion | public | t | BASE TABLE |",
+ "| datafusion | public | t2 | BASE TABLE |",
+ "+---------------+--------------------+------------+------------+",
+ ];
+ assert_batches_sorted_eq!(expected, &result);
+}
+
+#[tokio::test]
+async fn information_schema_tables_tables_with_multiple_catalogs() {
+ let mut ctx = ExecutionContext::with_config(
+ ExecutionConfig::new().with_information_schema(true),
+ );
+ let catalog = MemoryCatalogProvider::new();
+ let schema = MemorySchemaProvider::new();
+ schema
+ .register_table("t1".to_owned(), table_with_sequence(1, 1).unwrap())
+ .unwrap();
+ schema
+ .register_table("t2".to_owned(), table_with_sequence(1, 1).unwrap())
+ .unwrap();
+ catalog.register_schema("my_schema", Arc::new(schema));
+ ctx.register_catalog("my_catalog", Arc::new(catalog));
+
+ let catalog = MemoryCatalogProvider::new();
+ let schema = MemorySchemaProvider::new();
+ schema
+ .register_table("t3".to_owned(), table_with_sequence(1, 1).unwrap())
+ .unwrap();
+ catalog.register_schema("my_other_schema", Arc::new(schema));
+ ctx.register_catalog("my_other_catalog", Arc::new(catalog));
+
+ let result = plan_and_collect(&mut ctx, "SELECT * from
information_schema.tables")
+ .await
+ .unwrap();
+
+ let expected = vec![
+ "+------------------+--------------------+------------+------------+",
+ "| table_catalog | table_schema | table_name | table_type |",
+ "+------------------+--------------------+------------+------------+",
+ "| datafusion | information_schema | columns | VIEW |",
+ "| datafusion | information_schema | tables | VIEW |",
+ "| my_catalog | information_schema | columns | VIEW |",
+ "| my_catalog | information_schema | tables | 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 | tables | VIEW |",
+ "| my_other_catalog | my_other_schema | t3 | BASE TABLE |",
+ "+------------------+--------------------+------------+------------+",
+ ];
+ assert_batches_sorted_eq!(expected, &result);
+}
+
+#[tokio::test]
+async fn information_schema_tables_table_types() {
+ struct TestTable(TableType);
+
+ #[async_trait]
+ impl TableProvider for TestTable {
+ fn as_any(&self) -> &dyn std::any::Any {
+ self
+ }
+
+ fn table_type(&self) -> TableType {
+ self.0
+ }
+
+ fn schema(&self) -> SchemaRef {
+ unimplemented!()
+ }
+
+ async fn scan(
+ &self,
+ _: &Option<Vec<usize>>,
+ _: &[Expr],
+ _: Option<usize>,
+ ) -> Result<Arc<dyn ExecutionPlan>> {
+ unimplemented!()
+ }
+ }
+
+ let mut ctx = ExecutionContext::with_config(
+ ExecutionConfig::new().with_information_schema(true),
+ );
+
+ ctx.register_table("physical", Arc::new(TestTable(TableType::Base)))
+ .unwrap();
+ ctx.register_table("query", Arc::new(TestTable(TableType::View)))
+ .unwrap();
+ ctx.register_table("temp", Arc::new(TestTable(TableType::Temporary)))
+ .unwrap();
+
+ let result = plan_and_collect(&mut ctx, "SELECT * from
information_schema.tables")
+ .await
+ .unwrap();
+
+ let expected = vec![
+
"+---------------+--------------------+------------+-----------------+",
+ "| table_catalog | table_schema | table_name | table_type
|",
+
"+---------------+--------------------+------------+-----------------+",
+ "| datafusion | information_schema | tables | VIEW
|",
+ "| datafusion | information_schema | columns | VIEW
|",
+ "| datafusion | public | physical | BASE TABLE
|",
+ "| datafusion | public | query | VIEW
|",
+ "| datafusion | public | temp | LOCAL TEMPORARY
|",
+
"+---------------+--------------------+------------+-----------------+",
+ ];
+ assert_batches_sorted_eq!(expected, &result);
+}
+
+#[tokio::test]
+async fn information_schema_show_tables_no_information_schema() {
+ let mut ctx = ExecutionContext::with_config(ExecutionConfig::new());
+
+ ctx.register_table("t", table_with_sequence(1, 1).unwrap())
+ .unwrap();
+
+ // use show tables alias
+ let err = plan_and_collect(&mut ctx, "SHOW TABLES").await.unwrap_err();
+
+ assert_eq!(err.to_string(), "Error during planning: SHOW TABLES is not
supported unless information_schema is enabled");
+}
+
+#[tokio::test]
+async fn information_schema_show_tables() {
+ let mut ctx = ExecutionContext::with_config(
+ ExecutionConfig::new().with_information_schema(true),
+ );
+
+ ctx.register_table("t", table_with_sequence(1, 1).unwrap())
+ .unwrap();
+
+ // use show tables alias
+ let result = plan_and_collect(&mut ctx, "SHOW TABLES").await.unwrap();
+
+ let expected = vec![
+ "+---------------+--------------------+------------+------------+",
+ "| table_catalog | table_schema | table_name | table_type |",
+ "+---------------+--------------------+------------+------------+",
+ "| datafusion | information_schema | columns | VIEW |",
+ "| datafusion | information_schema | tables | VIEW |",
+ "| datafusion | public | t | BASE TABLE |",
+ "+---------------+--------------------+------------+------------+",
+ ];
+ assert_batches_sorted_eq!(expected, &result);
+
+ let result = plan_and_collect(&mut ctx, "SHOW tables").await.unwrap();
+
+ assert_batches_sorted_eq!(expected, &result);
+}
+
+#[tokio::test]
+async fn information_schema_show_columns_no_information_schema() {
+ let mut ctx = ExecutionContext::with_config(ExecutionConfig::new());
+
+ ctx.register_table("t", table_with_sequence(1, 1).unwrap())
+ .unwrap();
+
+ let err = plan_and_collect(&mut ctx, "SHOW COLUMNS FROM t")
+ .await
+ .unwrap_err();
+
+ assert_eq!(err.to_string(), "Error during planning: SHOW COLUMNS is not
supported unless information_schema is enabled");
+}
+
+#[tokio::test]
+async fn information_schema_show_columns_like_where() {
+ let mut ctx = ExecutionContext::with_config(ExecutionConfig::new());
+
+ ctx.register_table("t", table_with_sequence(1, 1).unwrap())
+ .unwrap();
+
+ let expected =
+ "Error during planning: SHOW COLUMNS with WHERE or LIKE is not
supported";
+
+ let err = plan_and_collect(&mut ctx, "SHOW COLUMNS FROM t LIKE 'f'")
+ .await
+ .unwrap_err();
+ assert_eq!(err.to_string(), expected);
+
+ let err = plan_and_collect(&mut ctx, "SHOW COLUMNS FROM t WHERE
column_name = 'bar'")
+ .await
+ .unwrap_err();
+ assert_eq!(err.to_string(), expected);
+}
+
+#[tokio::test]
+async fn information_schema_show_columns() {
+ let mut ctx = ExecutionContext::with_config(
+ ExecutionConfig::new().with_information_schema(true),
+ );
+
+ ctx.register_table("t", table_with_sequence(1, 1).unwrap())
+ .unwrap();
+
+ let result = plan_and_collect(&mut ctx, "SHOW COLUMNS FROM t")
+ .await
+ .unwrap();
+
+ let expected = vec![
+
"+---------------+--------------+------------+-------------+-----------+-------------+",
+ "| table_catalog | table_schema | table_name | column_name | data_type
| is_nullable |",
+
"+---------------+--------------+------------+-------------+-----------+-------------+",
+ "| datafusion | public | t | i | Int32
| YES |",
+
"+---------------+--------------+------------+-------------+-----------+-------------+",
+ ];
+ assert_batches_sorted_eq!(expected, &result);
+
+ let result = plan_and_collect(&mut ctx, "SHOW columns from t")
+ .await
+ .unwrap();
+ assert_batches_sorted_eq!(expected, &result);
+
+ // This isn't ideal but it is consistent behavior for `SELECT * from T`
+ let err = plan_and_collect(&mut ctx, "SHOW columns from T")
+ .await
+ .unwrap_err();
+ assert_eq!(
+ err.to_string(),
+ "Error during planning: Unknown relation for SHOW COLUMNS: T"
+ );
+}
+
+// test errors with WHERE and LIKE
+#[tokio::test]
+async fn information_schema_show_columns_full_extended() {
+ let mut ctx = ExecutionContext::with_config(
+ ExecutionConfig::new().with_information_schema(true),
+ );
+
+ ctx.register_table("t", table_with_sequence(1, 1).unwrap())
+ .unwrap();
+
+ let result = plan_and_collect(&mut ctx, "SHOW FULL COLUMNS FROM t")
+ .await
+ .unwrap();
+ let expected = vec![
+
"+---------------+--------------+------------+-------------+------------------+----------------+-------------+-----------+--------------------------+------------------------+-------------------+-------------------------+---------------+--------------------+---------------+",
+ "| table_catalog | table_schema | table_name | column_name |
ordinal_position | column_default | is_nullable | data_type |
character_maximum_length | character_octet_length | numeric_precision |
numeric_precision_radix | numeric_scale | datetime_precision | interval_type |",
+
"+---------------+--------------+------------+-------------+------------------+----------------+-------------+-----------+--------------------------+------------------------+-------------------+-------------------------+---------------+--------------------+---------------+",
+ "| datafusion | public | t | i | 0
| | YES | Int32 | |
| 32 | 2 |
| | |",
+
"+---------------+--------------+------------+-------------+------------------+----------------+-------------+-----------+--------------------------+------------------------+-------------------+-------------------------+---------------+--------------------+---------------+",
+ ];
+ assert_batches_sorted_eq!(expected, &result);
+
+ let result = plan_and_collect(&mut ctx, "SHOW EXTENDED COLUMNS FROM t")
+ .await
+ .unwrap();
+ assert_batches_sorted_eq!(expected, &result);
+}
+
+#[tokio::test]
+async fn information_schema_show_table_table_names() {
+ let mut ctx = ExecutionContext::with_config(
+ ExecutionConfig::new().with_information_schema(true),
+ );
+
+ ctx.register_table("t", table_with_sequence(1, 1).unwrap())
+ .unwrap();
+
+ let result = plan_and_collect(&mut ctx, "SHOW COLUMNS FROM public.t")
+ .await
+ .unwrap();
+
+ let expected = vec![
+
"+---------------+--------------+------------+-------------+-----------+-------------+",
+ "| table_catalog | table_schema | table_name | column_name | data_type
| is_nullable |",
+
"+---------------+--------------+------------+-------------+-----------+-------------+",
+ "| datafusion | public | t | i | Int32
| YES |",
+
"+---------------+--------------+------------+-------------+-----------+-------------+",
+ ];
+ assert_batches_sorted_eq!(expected, &result);
+
+ let result = plan_and_collect(&mut ctx, "SHOW columns from
datafusion.public.t")
+ .await
+ .unwrap();
+ assert_batches_sorted_eq!(expected, &result);
+
+ let err = plan_and_collect(&mut ctx, "SHOW columns from t2")
+ .await
+ .unwrap_err();
+ assert_eq!(
+ err.to_string(),
+ "Error during planning: Unknown relation for SHOW COLUMNS: t2"
+ );
+
+ let err = plan_and_collect(&mut ctx, "SHOW columns from
datafusion.public.t2")
+ .await
+ .unwrap_err();
+ assert_eq!(
+ err.to_string(),
+ "Error during planning: Unknown relation for SHOW COLUMNS:
datafusion.public.t2"
+ );
+}
+
+#[tokio::test]
+async fn show_unsupported() {
+ let mut ctx = ExecutionContext::with_config(ExecutionConfig::new());
+
+ let err = plan_and_collect(&mut 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 <TABLES>");
+}
+
+#[tokio::test]
+async fn information_schema_columns_not_exist_by_default() {
+ let mut ctx = ExecutionContext::new();
+
+ let err = plan_and_collect(&mut ctx, "SELECT * from
information_schema.columns")
+ .await
+ .unwrap_err();
+ assert_eq!(
+ err.to_string(),
+ "Error during planning: Table or CTE with name
'information_schema.columns' not found"
+ );
+}
+
+fn table_with_many_types() -> Arc<dyn TableProvider> {
+ let schema = Schema::new(vec![
+ Field::new("int32_col", DataType::Int32, false),
+ Field::new("float64_col", DataType::Float64, true),
+ Field::new("utf8_col", DataType::Utf8, true),
+ Field::new("large_utf8_col", DataType::LargeUtf8, false),
+ Field::new("binary_col", DataType::Binary, false),
+ Field::new("large_binary_col", DataType::LargeBinary, false),
+ Field::new(
+ "timestamp_nanos",
+ DataType::Timestamp(TimeUnit::Nanosecond, None),
+ false,
+ ),
+ ]);
+
+ let batch = RecordBatch::try_new(
+ Arc::new(schema.clone()),
+ vec![
+ Arc::new(Int32Array::from_slice(&[1])),
+ Arc::new(Float64Array::from_slice(&[1.0])),
+ Arc::new(StringArray::from(vec![Some("foo")])),
+ Arc::new(LargeStringArray::from(vec![Some("bar")])),
+ Arc::new(BinaryArray::from_slice(&[b"foo" as &[u8]])),
+ Arc::new(LargeBinaryArray::from_slice(&[b"foo" as &[u8]])),
+ Arc::new(TimestampNanosecondArray::from_opt_vec(
+ vec![Some(123)],
+ None,
+ )),
+ ],
+ )
+ .unwrap();
+ let provider = MemTable::try_new(Arc::new(schema),
vec![vec![batch]]).unwrap();
+ Arc::new(provider)
+}
+
+#[tokio::test]
+async fn information_schema_columns() {
+ let mut ctx = ExecutionContext::with_config(
+ ExecutionConfig::new().with_information_schema(true),
+ );
+ let catalog = MemoryCatalogProvider::new();
+ let schema = MemorySchemaProvider::new();
+
+ schema
+ .register_table("t1".to_owned(), table_with_sequence(1, 1).unwrap())
+ .unwrap();
+
+ schema
+ .register_table("t2".to_owned(), table_with_many_types())
+ .unwrap();
+ catalog.register_schema("my_schema", Arc::new(schema));
+ ctx.register_catalog("my_catalog", Arc::new(catalog));
+
+ let result = plan_and_collect(&mut ctx, "SELECT * from
information_schema.columns")
+ .await
+ .unwrap();
+
+ let expected = vec![
+
"+---------------+--------------+------------+------------------+------------------+----------------+-------------+-----------------------------+--------------------------+------------------------+-------------------+-------------------------+---------------+--------------------+---------------+",
+ "| table_catalog | table_schema | table_name | column_name |
ordinal_position | column_default | is_nullable | data_type |
character_maximum_length | character_octet_length | numeric_precision |
numeric_precision_radix | numeric_scale | datetime_precision | interval_type |",
+
"+---------------+--------------+------------+------------------+------------------+----------------+-------------+-----------------------------+--------------------------+------------------------+-------------------+-------------------------+---------------+--------------------+---------------+",
+ "| my_catalog | my_schema | t1 | i | 0
| | YES | Int32 |
| | 32 | 2
| | | |",
+ "| my_catalog | my_schema | t2 | binary_col | 4
| | NO | Binary |
| 2147483647 | |
| | | |",
+ "| my_catalog | my_schema | t2 | float64_col | 1
| | YES | Float64 |
| | 24 | 2
| | | |",
+ "| my_catalog | my_schema | t2 | int32_col | 0
| | NO | Int32 |
| | 32 | 2
| | | |",
+ "| my_catalog | my_schema | t2 | large_binary_col | 5
| | NO | LargeBinary |
| 9223372036854775807 | |
| | | |",
+ "| my_catalog | my_schema | t2 | large_utf8_col | 3
| | NO | LargeUtf8 |
| 9223372036854775807 | |
| | | |",
+ "| my_catalog | my_schema | t2 | timestamp_nanos | 6
| | NO | Timestamp(Nanosecond, None) |
| | |
| | | |",
+ "| my_catalog | my_schema | t2 | utf8_col | 2
| | YES | Utf8 |
| 2147483647 | |
| | | |",
+
"+---------------+--------------+------------+------------------+------------------+----------------+-------------+-----------------------------+--------------------------+------------------------+-------------------+-------------------------+---------------+--------------------+---------------+",
+ ];
+ assert_batches_sorted_eq!(expected, &result);
+}
+
+/// Execute SQL and return results
+async fn plan_and_collect(
+ ctx: &mut ExecutionContext,
+ sql: &str,
+) -> Result<Vec<RecordBatch>> {
+ ctx.sql(sql).await?.collect().await
+}
diff --git a/datafusion/tests/sql/mod.rs b/datafusion/tests/sql/mod.rs
index 55715af..f2496c3 100644
--- a/datafusion/tests/sql/mod.rs
+++ b/datafusion/tests/sql/mod.rs
@@ -29,6 +29,7 @@ use datafusion::assert_batches_eq;
use datafusion::assert_batches_sorted_eq;
use datafusion::assert_contains;
use datafusion::assert_not_contains;
+use datafusion::datasource::TableProvider;
use datafusion::from_slice::FromSlice;
use datafusion::logical_plan::plan::{Aggregate, Projection};
use datafusion::logical_plan::LogicalPlan;
@@ -95,6 +96,7 @@ pub mod udf;
pub mod union;
pub mod window;
+pub mod information_schema;
#[cfg_attr(not(feature = "unicode_expressions"), ignore)]
pub mod unicode;
@@ -693,6 +695,21 @@ fn make_timestamp_nano_table() -> Result<Arc<MemTable>> {
make_timestamp_table::<TimestampNanosecondType>()
}
+/// Return a new table provider that has a single Int32 column with
+/// values between `seq_start` and `seq_end`
+pub fn table_with_sequence(
+ seq_start: i32,
+ seq_end: i32,
+) -> Result<Arc<dyn TableProvider>> {
+ let schema = Arc::new(Schema::new(vec![Field::new("i", DataType::Int32,
true)]));
+ let arr =
Arc::new(Int32Array::from((seq_start..=seq_end).collect::<Vec<_>>()));
+ let partitions = vec![vec![RecordBatch::try_new(
+ schema.clone(),
+ vec![arr as ArrayRef],
+ )?]];
+ Ok(Arc::new(MemTable::try_new(schema, partitions)?))
+}
+
// Normalizes parts of an explain plan that vary from run to run (such as path)
fn normalize_for_explain(s: &str) -> String {
// Convert things like
/Users/alamb/Software/arrow/testing/data/csv/aggregate_test_100.csv