diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 96a966817..705395861 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -1045,6 +1045,16 @@ pub enum Statement { charset_name: String, collation_name: Option, }, + /// SET [ SESSION | LOCAL ] TIME ZONE timezone + /// + /// Note: this is a PostgreSQL-specific statement, + /// but may also compatible with other SQL. + SetTimeZone { + local: bool, + // SESSION is the default if neither SESSION nor LOCAL appears. + session: bool, + timezone: Expr, + }, /// SHOW /// /// Note: this is a PostgreSQL-specific statement. @@ -1849,6 +1859,20 @@ impl fmt::Display for Statement { Ok(()) } + Statement::SetTimeZone { + local, + session, + timezone, + } => { + let modifier = if *local { + "LOCAL " + } else if *session { + "SESSION " + } else { + "" + }; + write!(f, "SET {}TIME ZONE {}", modifier, timezone) + } Statement::ShowVariable { variable } => { write!(f, "SHOW")?; if !variable.is_empty() { diff --git a/src/parser.rs b/src/parser.rs index c28ee6f38..54f26f320 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -3769,6 +3769,19 @@ impl<'a> Parser<'a> { }); } + if dialect_of!(self is PostgreSqlDialect | RedshiftSqlDialect) + && self.parse_keywords(&[Keyword::TIME, Keyword::ZONE]) + { + let local = modifier == Some(Keyword::LOCAL); + let session = modifier == Some(Keyword::SESSION); + let timezone = self.parse_expr()?; + return Ok(Statement::SetTimeZone { + local, + session, + timezone, + }); + } + let mut key_values: Vec = vec![]; if dialect_of!(self is PostgreSqlDialect | RedshiftSqlDialect) { diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index 892f61ff3..860a3b312 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -949,6 +949,45 @@ fn parse_set_role() { ); } +#[test] +fn parse_set_time_zone() { + let stmt = pg().verified_stmt("SET SESSION TIME ZONE DEFAULT"); + assert_eq!( + stmt, + Statement::SetTimeZone { + local: false, + session: true, + timezone: Expr::Identifier(Ident { + value: "DEFAULT".to_string(), + quote_style: None, + }), + } + ); + + let stmt = pg().verified_stmt("SET LOCAL TIME ZONE 'Europe/Rome'"); + assert_eq!( + stmt, + Statement::SetTimeZone { + local: true, + session: false, + timezone: Expr::Value(Value::SingleQuotedString("Europe/Rome".to_string())), + } + ); + + let stmt = pg().verified_stmt("SET TIME ZONE LOCAL"); + assert_eq!( + stmt, + Statement::SetTimeZone { + local: false, + session: false, + timezone: Expr::Identifier(Ident { + value: "LOCAL".to_string(), + quote_style: None, + }), + } + ); +} + #[test] fn parse_show() { let stmt = pg_and_generic().verified_stmt("SHOW a a");