From bd1e38938fa45edd53809ab75d72676afe7fa1d9 Mon Sep 17 00:00:00 2001 From: TcMits Date: Fri, 8 Aug 2025 15:51:36 +0700 Subject: [PATCH] finish VACUUM --- parser/src/parser.rs | 65 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/parser/src/parser.rs b/parser/src/parser.rs index a4da20d72..dc955208f 100644 --- a/parser/src/parser.rs +++ b/parser/src/parser.rs @@ -500,6 +500,7 @@ impl<'a> Parser<'a> { TokenType::TK_ATTACH, TokenType::TK_DETACH, TokenType::TK_PRAGMA, + TokenType::TK_VACUUM, // add more ])?; @@ -516,6 +517,7 @@ impl<'a> Parser<'a> { TokenType::TK_ATTACH => self.parse_attach(), TokenType::TK_DETACH => self.parse_detach(), TokenType::TK_PRAGMA => self.parse_pragma(), + TokenType::TK_VACUUM => self.parse_vacuum(), _ => unreachable!(), } } @@ -2613,6 +2615,33 @@ impl<'a> Parser<'a> { }), } } + + fn parse_vacuum(&mut self) -> Result { + self.eat_assert(&[TokenType::TK_VACUUM]); + + let name = match self.peek()? { + Some(tok) => match tok.token_type.unwrap().fallback_id_if_ok() { + TokenType::TK_ID | TokenType::TK_STRING | TokenType::TK_INDEXED | TokenType::TK_JOIN_KW => { + Some(self.parse_nm()) + } + _ => None, + }, + _ => None, + }; + + let into = match self.peek()? { + Some(tok) if tok.token_type == Some(TokenType::TK_INTO) => { + self.eat_assert(&[TokenType::TK_INTO]); + Some(self.parse_expr(0)?) + } + _ => None, + }; + + Ok(Stmt::Vacuum { + name, + into, + }) + } } #[cfg(test)] @@ -7406,6 +7435,42 @@ mod tests { body: None, })], ), + // parse vacuum + ( + b"VACUUM".as_slice(), + vec![Cmd::Stmt(Stmt::Vacuum { + name: None, + into: None, + })], + ), + ( + b"VACUUM INTO 'foo'".as_slice(), + vec![Cmd::Stmt(Stmt::Vacuum { + name: None, + into: Some(Box::new(Expr::Literal(Literal::String("'foo'".to_owned())))), + })], + ), + ( + b"VACUUM INTO foo".as_slice(), + vec![Cmd::Stmt(Stmt::Vacuum { + name: None, + into: Some(Box::new(Expr::Id(Name::Ident("foo".to_owned())))), + })], + ), + ( + b"VACUUM foo".as_slice(), + vec![Cmd::Stmt(Stmt::Vacuum { + name: Some(Name::Ident("foo".to_owned())), + into: None, + })], + ), + ( + b"VACUUM foo INTO 'bar'".as_slice(), + vec![Cmd::Stmt(Stmt::Vacuum { + name: Some(Name::Ident("foo".to_owned())), + into: Some(Box::new(Expr::Literal(Literal::String("'bar'".to_owned())))), + })], + ), ]; for (input, expected) in test_cases {