diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 36c41d6ca..8112e2e56 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -4087,6 +4087,17 @@ pub enum Statement { show_options: ShowStatementOptions, }, /// ```sql + /// SHOW CATALOGS + /// ``` + ShowCatalogs { + /// `true` when terse output format was requested. + terse: bool, + /// `true` when history information was requested. + history: bool, + /// Additional options for `SHOW CATALOGS`. + show_options: ShowStatementOptions, + }, + /// ```sql /// SHOW DATABASES /// ``` ShowDatabases { @@ -5710,6 +5721,19 @@ impl fmt::Display for Statement { )?; Ok(()) } + Statement::ShowCatalogs { + terse, + history, + show_options, + } => { + write!( + f, + "SHOW {terse}CATALOGS{history}{show_options}", + terse = if *terse { "TERSE " } else { "" }, + history = if *history { " HISTORY" } else { "" }, + )?; + Ok(()) + } Statement::ShowSchemas { terse, history, diff --git a/src/ast/spans.rs b/src/ast/spans.rs index 2af57d98e..64dc23486 100644 --- a/src/ast/spans.rs +++ b/src/ast/spans.rs @@ -473,6 +473,7 @@ impl Spanned for Statement { Statement::AlterConnector { .. } => Span::empty(), Statement::DropPolicy { .. } => Span::empty(), Statement::DropConnector { .. } => Span::empty(), + Statement::ShowCatalogs { .. } => Span::empty(), Statement::ShowDatabases { .. } => Span::empty(), Statement::ShowSchemas { .. } => Span::empty(), Statement::ShowObjects { .. } => Span::empty(), diff --git a/src/keywords.rs b/src/keywords.rs index f0f37b1c0..fa17638d4 100644 --- a/src/keywords.rs +++ b/src/keywords.rs @@ -193,6 +193,7 @@ define_keywords!( CASES, CAST, CATALOG, + CATALOGS, CATALOG_SYNC, CATALOG_SYNC_NAMESPACE_FLATTEN_DELIMITER, CATALOG_SYNC_NAMESPACE_MODE, diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 3a970f7a1..91ce4e454 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -15071,6 +15071,8 @@ impl<'a> Parser<'a> { session, global, }) + } else if self.parse_keyword(Keyword::CATALOGS) { + self.parse_show_catalogs(terse) } else if self.parse_keyword(Keyword::DATABASES) { self.parse_show_databases(terse) } else if self.parse_keyword(Keyword::SCHEMAS) { @@ -15094,6 +15096,16 @@ impl<'a> Parser<'a> { })) } + fn parse_show_catalogs(&mut self, terse: bool) -> Result { + let history = self.parse_keyword(Keyword::HISTORY); + let show_options = self.parse_show_stmt_options()?; + Ok(Statement::ShowCatalogs { + terse, + history, + show_options, + }) + } + fn parse_show_databases(&mut self, terse: bool) -> Result { let history = self.parse_keyword(Keyword::HISTORY); let show_options = self.parse_show_stmt_options()?; diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index cff29bfec..a2715f72b 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -14740,6 +14740,7 @@ fn parse_method_expr() { fn test_show_dbs_schemas_tables_views() { // These statements are parsed the same by all dialects let stmts = vec![ + "SHOW CATALOGS", "SHOW DATABASES", "SHOW SCHEMAS", "SHOW TABLES", @@ -14757,7 +14758,11 @@ fn test_show_dbs_schemas_tables_views() { // 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'"]; + let stmts = vec![ + "SHOW CATALOGS LIKE '%abc'", + "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); diff --git a/tests/sqlparser_databricks.rs b/tests/sqlparser_databricks.rs index 79b3d0654..91db9a500 100644 --- a/tests/sqlparser_databricks.rs +++ b/tests/sqlparser_databricks.rs @@ -299,6 +299,66 @@ fn parse_use() { } } +#[test] +fn parse_show_catalogs() { + databricks().verified_stmt("SHOW CATALOGS"); + databricks().verified_stmt("SHOW TERSE CATALOGS"); + databricks().verified_stmt("SHOW CATALOGS HISTORY"); + databricks().verified_stmt("SHOW CATALOGS LIKE 'pay*'"); + databricks().verified_stmt("SHOW CATALOGS 'pay*'"); + databricks().verified_stmt("SHOW CATALOGS STARTS WITH 'pay'"); + databricks().verified_stmt("SHOW CATALOGS LIMIT 10"); + databricks().verified_stmt("SHOW CATALOGS HISTORY STARTS WITH 'pay'"); + + match databricks().verified_stmt("SHOW CATALOGS LIKE 'pay*'") { + Statement::ShowCatalogs { + terse, + history, + show_options, + } => { + assert!(!terse); + assert!(!history); + assert_eq!(show_options.show_in, None); + assert_eq!(show_options.starts_with, None); + assert_eq!(show_options.limit, None); + assert_eq!(show_options.limit_from, None); + assert_eq!( + show_options.filter_position, + Some(ShowStatementFilterPosition::Suffix( + ShowStatementFilter::Like("pay*".to_string()) + )) + ); + } + _ => unreachable!(), + } +} + +#[test] +fn parse_show_catalogs_with_show_options() { + databricks().verified_stmt("SHOW TERSE CATALOGS HISTORY IN ACCOUNT"); + + match databricks().verified_stmt("SHOW TERSE CATALOGS HISTORY IN ACCOUNT") { + Statement::ShowCatalogs { + terse, + history, + show_options, + } => { + assert!(terse); + assert!(history); + assert_eq!(show_options.filter_position, None); + assert!(matches!( + show_options.show_in, + Some(ShowStatementIn { + parent_type: Some(ShowStatementInParentType::Account), + parent_name: None, + .. + }) + )); + } + _ => unreachable!(), + } +} + #[test] fn parse_databricks_struct_function() { assert_eq!(