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

Reply via email to