Add support for Snowflake SHOW DATABASES/SCHEMAS/TABLES/VIEWS/COLUMNS statements (#1501)

This commit is contained in:
Yoav Cohen 2024-11-13 13:55:26 +02:00 committed by GitHub
parent 632ba4cf8e
commit 76322baf2f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 591 additions and 159 deletions

View file

@ -11395,23 +11395,43 @@ fn test_try_convert() {
#[test]
fn test_show_dbs_schemas_tables_views() {
verified_stmt("SHOW DATABASES");
verified_stmt("SHOW DATABASES LIKE '%abc'");
verified_stmt("SHOW SCHEMAS");
verified_stmt("SHOW SCHEMAS LIKE '%abc'");
verified_stmt("SHOW TABLES");
verified_stmt("SHOW TABLES IN db1");
verified_stmt("SHOW TABLES IN db1 'abc'");
verified_stmt("SHOW VIEWS");
verified_stmt("SHOW VIEWS IN db1");
verified_stmt("SHOW VIEWS IN db1 'abc'");
verified_stmt("SHOW VIEWS FROM db1");
verified_stmt("SHOW VIEWS FROM db1 'abc'");
verified_stmt("SHOW MATERIALIZED VIEWS");
verified_stmt("SHOW MATERIALIZED VIEWS IN db1");
verified_stmt("SHOW MATERIALIZED VIEWS IN db1 'abc'");
verified_stmt("SHOW MATERIALIZED VIEWS FROM db1");
verified_stmt("SHOW MATERIALIZED VIEWS FROM db1 'abc'");
// These statements are parsed the same by all dialects
let stmts = vec![
"SHOW DATABASES",
"SHOW SCHEMAS",
"SHOW TABLES",
"SHOW VIEWS",
"SHOW TABLES IN db1",
"SHOW VIEWS FROM db1",
"SHOW MATERIALIZED VIEWS",
"SHOW MATERIALIZED VIEWS IN db1",
"SHOW MATERIALIZED VIEWS FROM db1",
];
for stmt in stmts {
verified_stmt(stmt);
}
// These statements are parsed the same by all dialects
// except for how the parser interprets the location of
// LIKE option (infix/suffix)
let stmts = vec!["SHOW DATABASES LIKE '%abc'", "SHOW SCHEMAS LIKE '%abc'"];
for stmt in stmts {
all_dialects_where(|d| d.supports_show_like_before_in()).verified_stmt(stmt);
all_dialects_where(|d| !d.supports_show_like_before_in()).verified_stmt(stmt);
}
// These statements are only parsed by dialects that
// support the LIKE option in the suffix
let stmts = vec![
"SHOW TABLES IN db1 'abc'",
"SHOW VIEWS IN db1 'abc'",
"SHOW VIEWS FROM db1 'abc'",
"SHOW MATERIALIZED VIEWS IN db1 'abc'",
"SHOW MATERIALIZED VIEWS FROM db1 'abc'",
];
for stmt in stmts {
all_dialects_where(|d| !d.supports_show_like_before_in()).verified_stmt(stmt);
}
}
#[test]

View file

@ -223,14 +223,22 @@ fn parse_flush() {
#[test]
fn parse_show_columns() {
let table_name = ObjectName(vec![Ident::new("mytable")]);
assert_eq!(
mysql_and_generic().verified_stmt("SHOW COLUMNS FROM mytable"),
Statement::ShowColumns {
extended: false,
full: false,
table_name: table_name.clone(),
filter: None,
show_options: ShowStatementOptions {
show_in: Some(ShowStatementIn {
clause: ShowStatementInClause::FROM,
parent_type: None,
parent_name: Some(ObjectName(vec![Ident::new("mytable")])),
}),
filter_position: None,
limit_from: None,
limit: None,
starts_with: None,
}
}
);
assert_eq!(
@ -238,8 +246,17 @@ fn parse_show_columns() {
Statement::ShowColumns {
extended: false,
full: false,
table_name: ObjectName(vec![Ident::new("mydb"), Ident::new("mytable")]),
filter: None,
show_options: ShowStatementOptions {
show_in: Some(ShowStatementIn {
clause: ShowStatementInClause::FROM,
parent_type: None,
parent_name: Some(ObjectName(vec![Ident::new("mydb"), Ident::new("mytable")])),
}),
filter_position: None,
limit_from: None,
limit: None,
starts_with: None,
}
}
);
assert_eq!(
@ -247,8 +264,17 @@ fn parse_show_columns() {
Statement::ShowColumns {
extended: true,
full: false,
table_name: table_name.clone(),
filter: None,
show_options: ShowStatementOptions {
show_in: Some(ShowStatementIn {
clause: ShowStatementInClause::FROM,
parent_type: None,
parent_name: Some(ObjectName(vec![Ident::new("mytable")])),
}),
filter_position: None,
limit_from: None,
limit: None,
starts_with: None,
}
}
);
assert_eq!(
@ -256,8 +282,17 @@ fn parse_show_columns() {
Statement::ShowColumns {
extended: false,
full: true,
table_name: table_name.clone(),
filter: None,
show_options: ShowStatementOptions {
show_in: Some(ShowStatementIn {
clause: ShowStatementInClause::FROM,
parent_type: None,
parent_name: Some(ObjectName(vec![Ident::new("mytable")])),
}),
filter_position: None,
limit_from: None,
limit: None,
starts_with: None,
}
}
);
assert_eq!(
@ -265,8 +300,19 @@ fn parse_show_columns() {
Statement::ShowColumns {
extended: false,
full: false,
table_name: table_name.clone(),
filter: Some(ShowStatementFilter::Like("pattern".into())),
show_options: ShowStatementOptions {
show_in: Some(ShowStatementIn {
clause: ShowStatementInClause::FROM,
parent_type: None,
parent_name: Some(ObjectName(vec![Ident::new("mytable")])),
}),
filter_position: Some(ShowStatementFilterPosition::Suffix(
ShowStatementFilter::Like("pattern".into())
)),
limit_from: None,
limit: None,
starts_with: None,
}
}
);
assert_eq!(
@ -274,18 +320,27 @@ fn parse_show_columns() {
Statement::ShowColumns {
extended: false,
full: false,
table_name,
filter: Some(ShowStatementFilter::Where(
mysql_and_generic().verified_expr("1 = 2")
)),
show_options: ShowStatementOptions {
show_in: Some(ShowStatementIn {
clause: ShowStatementInClause::FROM,
parent_type: None,
parent_name: Some(ObjectName(vec![Ident::new("mytable")])),
}),
filter_position: Some(ShowStatementFilterPosition::Suffix(
ShowStatementFilter::Where(mysql_and_generic().verified_expr("1 = 2"))
)),
limit_from: None,
limit: None,
starts_with: None,
}
}
);
mysql_and_generic()
.one_statement_parses_to("SHOW FIELDS FROM mytable", "SHOW COLUMNS FROM mytable");
mysql_and_generic()
.one_statement_parses_to("SHOW COLUMNS IN mytable", "SHOW COLUMNS FROM mytable");
.one_statement_parses_to("SHOW COLUMNS IN mytable", "SHOW COLUMNS IN mytable");
mysql_and_generic()
.one_statement_parses_to("SHOW FIELDS IN mytable", "SHOW COLUMNS FROM mytable");
.one_statement_parses_to("SHOW FIELDS IN mytable", "SHOW COLUMNS IN mytable");
mysql_and_generic().one_statement_parses_to(
"SHOW COLUMNS FROM mytable FROM mydb",
"SHOW COLUMNS FROM mydb.mytable",
@ -327,63 +382,111 @@ fn parse_show_tables() {
assert_eq!(
mysql_and_generic().verified_stmt("SHOW TABLES"),
Statement::ShowTables {
terse: false,
history: false,
extended: false,
full: false,
clause: None,
db_name: None,
filter: None,
external: false,
show_options: ShowStatementOptions {
starts_with: None,
limit: None,
limit_from: None,
show_in: None,
filter_position: None
}
}
);
assert_eq!(
mysql_and_generic().verified_stmt("SHOW TABLES FROM mydb"),
Statement::ShowTables {
terse: false,
history: false,
extended: false,
full: false,
clause: Some(ShowClause::FROM),
db_name: Some(Ident::new("mydb")),
filter: None,
external: false,
show_options: ShowStatementOptions {
starts_with: None,
limit: None,
limit_from: None,
show_in: Some(ShowStatementIn {
clause: ShowStatementInClause::FROM,
parent_type: None,
parent_name: Some(ObjectName(vec![Ident::new("mydb")])),
}),
filter_position: None
}
}
);
assert_eq!(
mysql_and_generic().verified_stmt("SHOW EXTENDED TABLES"),
Statement::ShowTables {
terse: false,
history: false,
extended: true,
full: false,
clause: None,
db_name: None,
filter: None,
external: false,
show_options: ShowStatementOptions {
starts_with: None,
limit: None,
limit_from: None,
show_in: None,
filter_position: None
}
}
);
assert_eq!(
mysql_and_generic().verified_stmt("SHOW FULL TABLES"),
Statement::ShowTables {
terse: false,
history: false,
extended: false,
full: true,
clause: None,
db_name: None,
filter: None,
external: false,
show_options: ShowStatementOptions {
starts_with: None,
limit: None,
limit_from: None,
show_in: None,
filter_position: None
}
}
);
assert_eq!(
mysql_and_generic().verified_stmt("SHOW TABLES LIKE 'pattern'"),
Statement::ShowTables {
terse: false,
history: false,
extended: false,
full: false,
clause: None,
db_name: None,
filter: Some(ShowStatementFilter::Like("pattern".into())),
external: false,
show_options: ShowStatementOptions {
starts_with: None,
limit: None,
limit_from: None,
show_in: None,
filter_position: Some(ShowStatementFilterPosition::Suffix(
ShowStatementFilter::Like("pattern".into())
))
}
}
);
assert_eq!(
mysql_and_generic().verified_stmt("SHOW TABLES WHERE 1 = 2"),
Statement::ShowTables {
terse: false,
history: false,
extended: false,
full: false,
clause: None,
db_name: None,
filter: Some(ShowStatementFilter::Where(
mysql_and_generic().verified_expr("1 = 2")
)),
external: false,
show_options: ShowStatementOptions {
starts_with: None,
limit: None,
limit_from: None,
show_in: None,
filter_position: Some(ShowStatementFilterPosition::Suffix(
ShowStatementFilter::Where(mysql_and_generic().verified_expr("1 = 2"))
))
}
}
);
mysql_and_generic().verified_stmt("SHOW TABLES IN mydb");

View file

@ -2781,3 +2781,68 @@ fn test_parentheses_overflow() {
snowflake_with_recursion_limit(max_nesting_level).parse_sql_statements(sql.as_str());
assert_eq!(parsed.err(), Some(ParserError::RecursionLimitExceeded));
}
#[test]
fn test_show_databases() {
snowflake().verified_stmt("SHOW DATABASES");
snowflake().verified_stmt("SHOW DATABASES HISTORY");
snowflake().verified_stmt("SHOW DATABASES LIKE '%abc%'");
snowflake().verified_stmt("SHOW DATABASES STARTS WITH 'demo_db'");
snowflake().verified_stmt("SHOW DATABASES LIMIT 12");
snowflake()
.verified_stmt("SHOW DATABASES HISTORY LIKE '%aa' STARTS WITH 'demo' LIMIT 20 FROM 'abc'");
snowflake().verified_stmt("SHOW DATABASES IN ACCOUNT abc");
}
#[test]
fn test_parse_show_schemas() {
snowflake().verified_stmt("SHOW SCHEMAS");
snowflake().verified_stmt("SHOW SCHEMAS IN ACCOUNT");
snowflake().verified_stmt("SHOW SCHEMAS IN ACCOUNT abc");
snowflake().verified_stmt("SHOW SCHEMAS IN DATABASE");
snowflake().verified_stmt("SHOW SCHEMAS IN DATABASE xyz");
snowflake().verified_stmt("SHOW SCHEMAS HISTORY LIKE '%xa%'");
snowflake().verified_stmt("SHOW SCHEMAS STARTS WITH 'abc' LIMIT 20");
snowflake().verified_stmt("SHOW SCHEMAS IN DATABASE STARTS WITH 'abc' LIMIT 20 FROM 'xyz'");
}
#[test]
fn test_parse_show_tables() {
snowflake().verified_stmt("SHOW TABLES");
snowflake().verified_stmt("SHOW TABLES IN ACCOUNT");
snowflake().verified_stmt("SHOW TABLES IN DATABASE");
snowflake().verified_stmt("SHOW TABLES IN DATABASE xyz");
snowflake().verified_stmt("SHOW TABLES IN SCHEMA");
snowflake().verified_stmt("SHOW TABLES IN SCHEMA xyz");
snowflake().verified_stmt("SHOW TABLES HISTORY LIKE '%xa%'");
snowflake().verified_stmt("SHOW TABLES STARTS WITH 'abc' LIMIT 20");
snowflake().verified_stmt("SHOW TABLES IN SCHEMA STARTS WITH 'abc' LIMIT 20 FROM 'xyz'");
snowflake().verified_stmt("SHOW EXTERNAL TABLES");
snowflake().verified_stmt("SHOW EXTERNAL TABLES IN ACCOUNT");
snowflake().verified_stmt("SHOW EXTERNAL TABLES IN DATABASE");
snowflake().verified_stmt("SHOW EXTERNAL TABLES IN DATABASE xyz");
snowflake().verified_stmt("SHOW EXTERNAL TABLES IN SCHEMA");
snowflake().verified_stmt("SHOW EXTERNAL TABLES IN SCHEMA xyz");
snowflake().verified_stmt("SHOW EXTERNAL TABLES STARTS WITH 'abc' LIMIT 20");
snowflake()
.verified_stmt("SHOW EXTERNAL TABLES IN SCHEMA STARTS WITH 'abc' LIMIT 20 FROM 'xyz'");
}
#[test]
fn test_show_views() {
snowflake().verified_stmt("SHOW VIEWS");
snowflake().verified_stmt("SHOW VIEWS IN ACCOUNT");
snowflake().verified_stmt("SHOW VIEWS IN DATABASE");
snowflake().verified_stmt("SHOW VIEWS IN DATABASE xyz");
snowflake().verified_stmt("SHOW VIEWS IN SCHEMA");
snowflake().verified_stmt("SHOW VIEWS IN SCHEMA xyz");
snowflake().verified_stmt("SHOW VIEWS STARTS WITH 'abc' LIMIT 20");
snowflake().verified_stmt("SHOW VIEWS IN SCHEMA STARTS WITH 'abc' LIMIT 20 FROM 'xyz'");
}
#[test]
fn test_parse_show_columns_sql() {
snowflake().verified_stmt("SHOW COLUMNS IN TABLE");
snowflake().verified_stmt("SHOW COLUMNS IN TABLE abc");
snowflake().verified_stmt("SHOW COLUMNS LIKE '%xyz%' IN TABLE abc");
}