Skip to content

Commit

Permalink
Minor: Port information schema tests to sqllogictest (#4905)
Browse files Browse the repository at this point in the history
  • Loading branch information
alamb authored Jan 15, 2023
1 parent 195eccf commit f376270
Show file tree
Hide file tree
Showing 2 changed files with 213 additions and 365 deletions.
365 changes: 0 additions & 365 deletions datafusion/core/tests/sql/information_schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ use datafusion::{
};
use datafusion_expr::Expr;

use rstest::rstest;

use super::*;

#[tokio::test]
Expand Down Expand Up @@ -144,277 +142,6 @@ async fn information_schema_tables_table_types() {
assert_batches_sorted_eq!(expected, &result);
}

#[tokio::test]
async fn information_schema_show_tables_no_information_schema() {
let ctx = SessionContext::with_config(SessionConfig::new());

ctx.register_table("t", table_with_sequence(1, 1).unwrap())
.unwrap();

// use show tables alias
let err = plan_and_collect(&ctx, "SHOW TABLES").await.unwrap_err();

assert_eq!(err.to_string(), "Error during planning: SHOW TABLES is not supported unless information_schema is enabled");
}

#[rstest]
#[case("datafusion.public.some_table")]
#[case("public.some_table")]
#[case("some_table")]
#[tokio::test]
async fn information_schema_describe_table(#[case] table_name: &str) {
let ctx =
SessionContext::with_config(SessionConfig::new().with_information_schema(true));

let sql = format!("CREATE OR REPLACE TABLE {table_name} AS VALUES (1,2),(3,4);");
ctx.sql(sql.as_str()).await.unwrap();

let sql_all = format!("DESCRIBE {table_name};");
let results_all = execute_to_batches(&ctx, sql_all.as_str()).await;

let expected = vec![
"+-------------+-----------+-------------+",
"| column_name | data_type | is_nullable |",
"+-------------+-----------+-------------+",
"| column1 | Int64 | YES |",
"| column2 | Int64 | YES |",
"+-------------+-----------+-------------+",
];

assert_batches_eq!(expected, &results_all);
}

#[tokio::test]
async fn information_schema_describe_table_not_exists() {
let ctx = SessionContext::with_config(SessionConfig::new());

let sql_all = "describe table;";
let err = plan_and_collect(&ctx, sql_all).await.unwrap_err();
assert_eq!(
err.to_string(),
"Error during planning: table 'datafusion.public.table' not found"
);
}

#[tokio::test]
async fn information_schema_show_tables() {
let ctx =
SessionContext::with_config(SessionConfig::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(&ctx, "SHOW TABLES").await.unwrap();

let expected = vec![
"+---------------+--------------------+-------------+------------+",
"| table_catalog | table_schema | table_name | table_type |",
"+---------------+--------------------+-------------+------------+",
"| datafusion | information_schema | columns | VIEW |",
"| datafusion | information_schema | df_settings | VIEW |",
"| datafusion | information_schema | tables | VIEW |",
"| datafusion | information_schema | views | VIEW |",
"| datafusion | public | t | BASE TABLE |",
"+---------------+--------------------+-------------+------------+",
];
assert_batches_sorted_eq!(expected, &result);

let result = plan_and_collect(&ctx, "SHOW tables").await.unwrap();

assert_batches_sorted_eq!(expected, &result);
}

#[tokio::test]
async fn information_schema_show_columns_no_information_schema() {
let ctx = SessionContext::with_config(SessionConfig::new());

ctx.register_table("t", table_with_sequence(1, 1).unwrap())
.unwrap();

let err = plan_and_collect(&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 ctx = SessionContext::with_config(SessionConfig::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(&ctx, "SHOW COLUMNS FROM t LIKE 'f'")
.await
.unwrap_err();
assert_eq!(err.to_string(), expected);

let err = plan_and_collect(&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 ctx =
SessionContext::with_config(SessionConfig::new().with_information_schema(true));

ctx.register_table("t", table_with_sequence(1, 1).unwrap())
.unwrap();

let result = plan_and_collect(&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(&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(&ctx, "SHOW columns from \"T\"")
.await
.unwrap_err();
assert_eq!(
err.to_string(),
// Error propagates from SessionState::get_table_provider
"Error during planning: table 'datafusion.public.T' not found"
);
}

// test errors with WHERE and LIKE
#[tokio::test]
async fn information_schema_show_columns_full_extended() {
let ctx =
SessionContext::with_config(SessionConfig::new().with_information_schema(true));

ctx.register_table("t", table_with_sequence(1, 1).unwrap())
.unwrap();

let result = plan_and_collect(&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(&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 ctx =
SessionContext::with_config(SessionConfig::new().with_information_schema(true));

ctx.register_table("t", table_with_sequence(1, 1).unwrap())
.unwrap();

let result = plan_and_collect(&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(&ctx, "SHOW columns from datafusion.public.t")
.await
.unwrap();
assert_batches_sorted_eq!(expected, &result);

let err = plan_and_collect(&ctx, "SHOW columns from t2")
.await
.unwrap_err();
assert_eq!(
err.to_string(),
// Error propagates from SessionState::get_table_provider
"Error during planning: table 'datafusion.public.t2' not found"
);

let err = plan_and_collect(&ctx, "SHOW columns from datafusion.public.t2")
.await
.unwrap_err();
assert_eq!(
err.to_string(),
// Error propagates from SessionState::get_table_provider
"Error during planning: table 'datafusion.public.t2' not found"
);
}

// FIXME once we support raise error while show non-existing variable, we could add this back
//#[tokio::test]
//async fn show_unsupported() {
// let ctx = SessionContext::with_config(SessionConfig::new());
//
// let err = plan_and_collect(&ctx, "SHOW SOMETHING_UNKNOWN")
// .await
// .unwrap_err();
//
// assert_eq!(err.to_string(), "This feature is not implemented: SHOW SOMETHING_UNKNOWN not implemented. Supported syntax: SHOW <TABLES>");
//}

// FIXME
// currently we cannot know whether a variable exists, this will output 0 row instead
// one way to fix this is to generate a ConfigOptions and get options' key to compare
// however config.rs is currently in core lib, could not be used by datafusion_sql due to the dependency cycle
#[tokio::test]
async fn show_non_existing_variable() {
let ctx =
SessionContext::with_config(SessionConfig::new().with_information_schema(true));

let result = plan_and_collect(&ctx, "SHOW SOMETHING_UNKNOWN")
.await
.unwrap();

assert_eq!(result.len(), 0);
}

#[tokio::test]
async fn show_unsupported_when_information_schema_off() {
let ctx = SessionContext::with_config(SessionConfig::new());

let err = plan_and_collect(&ctx, "SHOW SOMETHING").await.unwrap_err();

assert_eq!(err.to_string(), "Error during planning: SHOW [VARIABLE] is not supported unless information_schema is enabled");
}

#[tokio::test]
async fn information_schema_columns_not_exist_by_default() {
let ctx = SessionContext::new();

let err = plan_and_collect(&ctx, "SELECT * from information_schema.columns")
.await
.unwrap_err();
assert_eq!(
err.to_string(),
"Error during planning: table 'datafusion.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),
Expand Down Expand Up @@ -487,98 +214,6 @@ async fn information_schema_columns() {
assert_batches_sorted_eq!(expected, &result);
}

#[tokio::test]
async fn show_create_view() {
let ctx =
SessionContext::with_config(SessionConfig::new().with_information_schema(true));
let table_sql = "CREATE TABLE abc AS VALUES (1,2,3), (4,5,6)";
plan_and_collect(&ctx, table_sql).await.unwrap();
let view_sql = "CREATE VIEW xyz AS SELECT * FROM abc";
plan_and_collect(&ctx, view_sql).await.unwrap();

let results_sql = "SHOW CREATE TABLE xyz";
let results = plan_and_collect(&ctx, results_sql).await.unwrap();
assert_eq!(results[0].num_rows(), 1);

let expected = vec![
"+---------------+--------------+------------+--------------------------------------+",
"| table_catalog | table_schema | table_name | definition |",
"+---------------+--------------+------------+--------------------------------------+",
"| datafusion | public | xyz | CREATE VIEW xyz AS SELECT * FROM abc |",
"+---------------+--------------+------------+--------------------------------------+",
];
assert_batches_eq!(expected, &results);
}

#[tokio::test]
async fn show_create_view_in_catalog() {
let ctx =
SessionContext::with_config(SessionConfig::new().with_information_schema(true));
let table_sql = "CREATE TABLE abc AS VALUES (1,2,3), (4,5,6)";
plan_and_collect(&ctx, table_sql).await.unwrap();
let schema_sql = "CREATE SCHEMA test";
plan_and_collect(&ctx, schema_sql).await.unwrap();
let view_sql = "CREATE VIEW test.xyz AS SELECT * FROM abc";
plan_and_collect(&ctx, view_sql).await.unwrap();

let result_sql = "SHOW CREATE TABLE test.xyz";
let results = plan_and_collect(&ctx, result_sql).await.unwrap();
assert_eq!(results[0].num_rows(), 1);

let expected = vec![
"+---------------+--------------+------------+-------------------------------------------+",
"| table_catalog | table_schema | table_name | definition |",
"+---------------+--------------+------------+-------------------------------------------+",
"| datafusion | test | xyz | CREATE VIEW test.xyz AS SELECT * FROM abc |",
"+---------------+--------------+------------+-------------------------------------------+",
];
assert_batches_eq!(expected, &results);
}

#[tokio::test]
async fn show_create_table() {
let ctx =
SessionContext::with_config(SessionConfig::new().with_information_schema(true));
let table_sql = "CREATE TABLE abc AS VALUES (1,2,3), (4,5,6)";
plan_and_collect(&ctx, table_sql).await.unwrap();

let result_sql = "SHOW CREATE TABLE abc";
let results = plan_and_collect(&ctx, result_sql).await.unwrap();

let expected = vec![
"+---------------+--------------+------------+------------+",
"| table_catalog | table_schema | table_name | definition |",
"+---------------+--------------+------------+------------+",
"| datafusion | public | abc | |",
"+---------------+--------------+------------+------------+",
];

assert_batches_eq!(expected, &results);
}

#[tokio::test]
async fn show_external_create_table() {
let ctx =
SessionContext::with_config(SessionConfig::new().with_information_schema(true));

let table_sql =
"CREATE EXTERNAL TABLE abc STORED AS CSV WITH HEADER ROW LOCATION '../../testing/data/csv/aggregate_test_100.csv'";
plan_and_collect(&ctx, table_sql).await.unwrap();

let result_sql = "SHOW CREATE TABLE abc";
let results = plan_and_collect(&ctx, result_sql).await.unwrap();

let expected = vec![
"+---------------+--------------+------------+-------------------------------------------------------------------------------------------------+",
"| table_catalog | table_schema | table_name | definition |",
"+---------------+--------------+------------+-------------------------------------------------------------------------------------------------+",
"| datafusion | public | abc | CREATE EXTERNAL TABLE abc STORED AS CSV LOCATION ../../testing/data/csv/aggregate_test_100.csv |",
"+---------------+--------------+------------+-------------------------------------------------------------------------------------------------+",
];

assert_batches_eq!(expected, &results);
}

/// Execute SQL and return results
async fn plan_and_collect(ctx: &SessionContext, sql: &str) -> Result<Vec<RecordBatch>> {
ctx.sql(sql).await?.collect().await
Expand Down
Loading

0 comments on commit f376270

Please sign in to comment.