diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 46af91962..a92794d3b 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -4126,6 +4126,21 @@ pub enum Statement { session: bool, }, /// ```sql + /// SHOW PARAMETERS + /// [ LIKE '' ] + /// [ { IN | FOR } { SESSION | ACCOUNT | USER | WAREHOUSE | + /// DATABASE | SCHEMA | TASK | TABLE } [ ] ] + /// ``` + /// + /// Snowflake-specific statement. + /// + ShowParameters { + /// Optional case-insensitive name pattern. + filter: Option, + /// Optional parameter scope. + show_in: Option, + }, + /// ```sql /// SHOW CREATE TABLE /// ``` /// @@ -5833,6 +5848,16 @@ impl fmt::Display for Statement { } Ok(()) } + Statement::ShowParameters { filter, show_in } => { + write!(f, "SHOW PARAMETERS")?; + if let Some(filter) = filter { + write!(f, " {filter}")?; + } + if let Some(show_in) = show_in { + write!(f, " {show_in}")?; + } + Ok(()) + } Statement::ShowCreate { obj_type, obj_name } => { write!(f, "SHOW CREATE {obj_type} {obj_name}",)?; Ok(()) @@ -9265,12 +9290,14 @@ impl fmt::Display for ShowStatementFilter { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] -/// Clause types used with SHOW ... IN/FROM. +/// Clause types used with SHOW ... IN/FROM/FOR. pub enum ShowStatementInClause { /// Use the `IN` clause. IN, /// Use the `FROM` clause. FROM, + /// Use the `FOR` clause. + FOR, } impl fmt::Display for ShowStatementInClause { @@ -9279,6 +9306,7 @@ impl fmt::Display for ShowStatementInClause { match self { FROM => write!(f, "FROM"), IN => write!(f, "IN"), + FOR => write!(f, "FOR"), } } } @@ -10937,12 +10965,20 @@ pub enum ShowStatementFilterPosition { pub enum ShowStatementInParentType { /// ACCOUNT parent type for SHOW statements. Account, + /// SESSION parent type for SHOW statements. + Session, + /// USER parent type for SHOW statements. + User, + /// WAREHOUSE parent type for SHOW statements. + Warehouse, /// DATABASE parent type for SHOW statements. Database, /// SCHEMA parent type for SHOW statements. Schema, /// TABLE parent type for SHOW statements. Table, + /// TASK parent type for SHOW statements. + Task, /// VIEW parent type for SHOW statements. View, } @@ -10951,9 +10987,13 @@ impl fmt::Display for ShowStatementInParentType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { ShowStatementInParentType::Account => write!(f, "ACCOUNT"), + ShowStatementInParentType::Session => write!(f, "SESSION"), + ShowStatementInParentType::User => write!(f, "USER"), + ShowStatementInParentType::Warehouse => write!(f, "WAREHOUSE"), ShowStatementInParentType::Database => write!(f, "DATABASE"), ShowStatementInParentType::Schema => write!(f, "SCHEMA"), ShowStatementInParentType::Table => write!(f, "TABLE"), + ShowStatementInParentType::Task => write!(f, "TASK"), ShowStatementInParentType::View => write!(f, "VIEW"), } } diff --git a/src/ast/spans.rs b/src/ast/spans.rs index afc289c10..adcda1381 100644 --- a/src/ast/spans.rs +++ b/src/ast/spans.rs @@ -439,6 +439,7 @@ impl Spanned for Statement { Statement::ShowVariable { .. } => Span::empty(), Statement::ShowStatus { .. } => Span::empty(), Statement::ShowVariables { .. } => Span::empty(), + Statement::ShowParameters { .. } => Span::empty(), Statement::ShowCreate { .. } => Span::empty(), Statement::ShowColumns { .. } => Span::empty(), Statement::ShowTables { .. } => Span::empty(), diff --git a/src/keywords.rs b/src/keywords.rs index e008fc035..12d17d084 100644 --- a/src/keywords.rs +++ b/src/keywords.rs @@ -767,6 +767,7 @@ define_keywords!( PACK_KEYS, PARALLEL, PARAMETER, + PARAMETERS, PARQUET, PART, PARTIAL, diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 860f24e4f..dc793991f 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -15546,6 +15546,8 @@ impl<'a> Parser<'a> { session, global, }) + } else if self.parse_keyword(Keyword::PARAMETERS) && dialect_of!(self is SnowflakeDialect) { + self.parse_show_parameters() } else if self.parse_keyword(Keyword::STATUS) && dialect_of!(self is MySqlDialect | GenericDialect) { @@ -15571,6 +15573,63 @@ impl<'a> Parser<'a> { } } + fn parse_show_parameters(&mut self) -> Result { + let filter = if self.parse_keyword(Keyword::LIKE) { + Some(ShowStatementFilter::Like(self.parse_literal_string()?)) + } else { + None + }; + + let clause = match self.parse_one_of_keywords(&[Keyword::IN, Keyword::FOR]) { + Some(Keyword::IN) => Some(ShowStatementInClause::IN), + Some(Keyword::FOR) => Some(ShowStatementInClause::FOR), + None => None, + _ => { + return self.expected_ref("IN or FOR", self.peek_token_ref()); + } + }; + + let show_in = if let Some(clause) = clause { + let parent_type = + match self.parse_one_of_keywords(&[ + Keyword::SESSION, + Keyword::ACCOUNT, + Keyword::USER, + Keyword::WAREHOUSE, + Keyword::DATABASE, + Keyword::SCHEMA, + Keyword::TASK, + Keyword::TABLE, + ]) { + Some(Keyword::SESSION) => ShowStatementInParentType::Session, + Some(Keyword::ACCOUNT) => ShowStatementInParentType::Account, + Some(Keyword::USER) => ShowStatementInParentType::User, + Some(Keyword::WAREHOUSE) => ShowStatementInParentType::Warehouse, + Some(Keyword::DATABASE) => ShowStatementInParentType::Database, + Some(Keyword::SCHEMA) => ShowStatementInParentType::Schema, + Some(Keyword::TASK) => ShowStatementInParentType::Task, + Some(Keyword::TABLE) => ShowStatementInParentType::Table, + _ => return self.expected_ref( + "one of SESSION, ACCOUNT, USER, WAREHOUSE, DATABASE, SCHEMA, TASK or TABLE", + self.peek_token_ref(), + ), + }; + let parent_name = match parent_type { + ShowStatementInParentType::Session | ShowStatementInParentType::Account => None, + _ => self.maybe_parse(|parser| parser.parse_object_name(false))?, + }; + Some(ShowStatementIn { + clause, + parent_type: Some(parent_type), + parent_name, + }) + } else { + None + }; + + Ok(Statement::ShowParameters { filter, show_in }) + } + fn parse_show_charset(&mut self, is_shorthand: bool) -> Result { // parse one of keywords Ok(Statement::ShowCharset(ShowCharset { diff --git a/tests/sqlparser_snowflake.rs b/tests/sqlparser_snowflake.rs index b71d27772..c1d7633b9 100644 --- a/tests/sqlparser_snowflake.rs +++ b/tests/sqlparser_snowflake.rs @@ -3573,6 +3573,33 @@ fn test_show_databases() { snowflake().verified_stmt("SHOW DATABASES IN ACCOUNT abc"); } +#[test] +fn test_show_parameters() { + snowflake().verified_stmt("SHOW PARAMETERS"); + snowflake().verified_stmt("SHOW PARAMETERS LIKE 'TIME%'"); + snowflake().verified_stmt("SHOW PARAMETERS IN SESSION"); + snowflake().verified_stmt("SHOW PARAMETERS FOR ACCOUNT"); + snowflake().verified_stmt("SHOW PARAMETERS IN USER analyst"); + snowflake().verified_stmt("SHOW PARAMETERS IN WAREHOUSE analytics_wh"); + snowflake().verified_stmt("SHOW PARAMETERS IN DATABASE analytics"); + snowflake().verified_stmt("SHOW PARAMETERS IN SCHEMA analytics.public"); + snowflake().verified_stmt("SHOW PARAMETERS IN TASK analytics.public.refresh_task"); + snowflake().verified_stmt("SHOW PARAMETERS IN TABLE analytics.public.events"); + + match snowflake().verified_stmt("SHOW PARAMETERS LIKE '%TIME%' FOR SESSION") { + Statement::ShowParameters { + filter: Some(ShowStatementFilter::Like(pattern)), + show_in: + Some(ShowStatementIn { + clause: ShowStatementInClause::FOR, + parent_type: Some(ShowStatementInParentType::Session), + parent_name: None, + }), + } => assert_eq!(pattern, "%TIME%"), + statement => panic!("unexpected statement: {statement:?}"), + } +} + #[test] fn test_parse_show_schemas() { snowflake().verified_stmt("SHOW SCHEMAS");