diff --git a/src/ast/mod.rs b/src/ast/mod.rs index e65ef35..3d73918 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -2146,7 +2146,7 @@ pub enum Statement { if_not_exists: bool, create_mirror: CreateMirror, }, - /// DROP MIRROR [IF EXISTS] mirror_name + // DROP MIRROR [IF EXISTS] mirror_name DropMirror { #[cfg_attr(feature = "derive-visitor", drive(skip))] if_exists: bool, @@ -2162,6 +2162,18 @@ pub enum Statement { mirror_name: ObjectName, with_options: Vec, }, + // DROP MIRROR [IF EXISTS] mirror_name + PauseMirror { + #[cfg_attr(feature = "derive-visitor", drive(skip))] + if_exists: bool, + mirror_name: ObjectName, + }, + // RESUME MIRROR [IF EXISTS] mirror_name + ResumeMirror { + #[cfg_attr(feature = "derive-visitor", drive(skip))] + if_exists: bool, + mirror_name: ObjectName, + }, } #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] @@ -3656,6 +3668,28 @@ impl fmt::Display for Statement { write!(f, "EXECUTE MIRROR {mirror_name}", mirror_name = mirror_name)?; Ok(()) } + Statement::PauseMirror { + if_exists, + mirror_name, + } => { + write!( + f, + "PAUSE MIRROR {if_exists}{mirror_name}", + if_exists = if *if_exists { "IF EXISTS " } else { "" }, + )?; + Ok(()) + } + Statement::ResumeMirror { + if_exists, + mirror_name, + } => { + write!( + f, + "RESUME MIRROR {if_exists}{mirror_name}", + if_exists = if *if_exists { "IF EXISTS " } else { "" }, + )?; + Ok(()) + } Statement::ResyncMirror { if_exists, mirror_name, diff --git a/src/keywords.rs b/src/keywords.rs index c9210c5..9f5d11c 100644 --- a/src/keywords.rs +++ b/src/keywords.rs @@ -471,6 +471,7 @@ define_keywords!( PARTITIONS, PASSWORD, PATTERN, + PAUSE, PEER, PERCENT, PERCENTILE_CONT, @@ -534,6 +535,7 @@ define_keywords!( RESPECT, RESTRICT, RESULT, + RESUME, RESYNC, RETAIN, RETURN, diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 3685b70..0b9c9aa 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -522,6 +522,8 @@ impl<'a> Parser<'a> { // `PRAGMA` is sqlite specific https://www.sqlite.org/pragma.html Keyword::PRAGMA => Ok(self.parse_pragma()?), Keyword::RESYNC => Ok(self.parse_resync()?), + Keyword::PAUSE => Ok(self.parse_pause_mirror()?), + Keyword::RESUME => Ok(self.parse_resume_mirror()?), _ => self.expected("an SQL statement", next_token), }, Token::LParen => { @@ -8104,6 +8106,26 @@ impl<'a> Parser<'a> { }) } + pub fn parse_pause_mirror(&mut self) -> Result { + self.expect_keyword(Keyword::MIRROR)?; + let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]); + let mirror_name = self.parse_object_name()?; + Ok(Statement::PauseMirror { + if_exists, + mirror_name, + }) + } + + pub fn parse_resume_mirror(&mut self) -> Result { + self.expect_keyword(Keyword::MIRROR)?; + let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]); + let mirror_name = self.parse_object_name()?; + Ok(Statement::ResumeMirror { + if_exists, + mirror_name, + }) + } + /// The index of the first unprocessed token. pub fn index(&self) -> usize { self.index diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index 8288d21..24a7699 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -3610,6 +3610,20 @@ fn parse_create_mirror_with_schema() { #[test] fn parse_drop_mirror() { + match pg().verified_stmt("DROP MIRROR m1") { + Statement::DropMirror { + if_exists, + mirror_name, + } => { + assert!(!if_exists); + assert_eq!(mirror_name, ObjectName(vec![Ident::new("m1")])); + } + _ => unreachable!(), + } +} + +#[test] +fn parse_drop_mirror_if_exists() { match pg().verified_stmt("DROP MIRROR IF EXISTS m1") { Statement::DropMirror { if_exists, @@ -3622,8 +3636,78 @@ fn parse_drop_mirror() { } } +#[test] +fn parse_pause_mirror() { + match pg().verified_stmt("PAUSE MIRROR m1") { + Statement::PauseMirror { + if_exists, + mirror_name, + } => { + assert!(!if_exists); + assert_eq!(mirror_name, ObjectName(vec![Ident::new("m1")])); + } + _ => unreachable!(), + } +} + +#[test] +fn parse_pause_mirror_if_exists() { + match pg().verified_stmt("PAUSE MIRROR IF EXISTS m1") { + Statement::PauseMirror { + if_exists, + mirror_name, + } => { + assert!(if_exists); + assert_eq!(mirror_name, ObjectName(vec![Ident::new("m1")])); + } + _ => unreachable!(), + } +} + +#[test] +fn parse_resume_mirror() { + match pg().verified_stmt("RESUME MIRROR m1") { + Statement::ResumeMirror { + if_exists, + mirror_name, + } => { + assert!(!if_exists); + assert_eq!(mirror_name, ObjectName(vec![Ident::new("m1")])); + } + _ => unreachable!(), + } +} + +#[test] +fn parse_resume_mirror_if_exists() { + match pg().verified_stmt("RESUME MIRROR IF EXISTS m1") { + Statement::ResumeMirror { + if_exists, + mirror_name, + } => { + assert!(if_exists); + assert_eq!(mirror_name, ObjectName(vec![Ident::new("m1")])); + } + _ => unreachable!(), + } +} + #[test] fn parse_drop_peer() { + match pg().verified_stmt("DROP PEER p1") { + Statement::DropPeer { + if_exists, + peer_name, + } => { + assert!(!if_exists); + assert_eq!(peer_name, ObjectName(vec![Ident::new("p1")])); + } + _ => unreachable!(), + } +} + +#[test] +fn parse_drop_peer_if_exists() { match pg().verified_stmt("DROP PEER IF EXISTS p1") { Statement::DropPeer { if_exists,