Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit e9eee00

Browse files
Add support for VACUUM in Redshift (#2005)
1 parent cb7a51e commit e9eee00

File tree

5 files changed

+138
-0
lines changed

5 files changed

+138
-0
lines changed

‎src/ast/mod.rs‎

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4409,6 +4409,13 @@ pub enum Statement {
44094409
/// ```
44104410
/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
44114411
CreateUser(CreateUser),
4412+
/// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
4413+
///
4414+
/// ```sql
4415+
/// VACUUM tbl
4416+
/// ```
4417+
/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
4418+
Vacuum(VacuumStatement),
44124419
}
44134420

44144421
/// ```sql
@@ -6343,6 +6350,7 @@ impl fmt::Display for Statement {
63436350
Statement::ExportData(e) => write!(f, "{e}"),
63446351
Statement::CreateUser(s) => write!(f, "{s}"),
63456352
Statement::AlterSchema(s) => write!(f, "{s}"),
6353+
Statement::Vacuum(s) => write!(f, "{s}"),
63466354
}
63476355
}
63486356
}
@@ -10604,6 +10612,50 @@ impl fmt::Display for InitializeKind {
1060410612
}
1060510613
}
1060610614

10615+
/// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
10616+
///
10617+
/// '''sql
10618+
/// VACUUM [ FULL | SORT ONLY | DELETE ONLY | REINDEX | RECLUSTER ] [ \[ table_name \] [ TO threshold PERCENT ] \[ BOOST \] ]
10619+
/// '''
10620+
/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
10621+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10622+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10623+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10624+
pub struct VacuumStatement {
10625+
pub full: bool,
10626+
pub sort_only: bool,
10627+
pub delete_only: bool,
10628+
pub reindex: bool,
10629+
pub recluster: bool,
10630+
pub table_name: Option<ObjectName>,
10631+
pub threshold: Option<Value>,
10632+
pub boost: bool,
10633+
}
10634+
10635+
impl fmt::Display for VacuumStatement {
10636+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10637+
write!(
10638+
f,
10639+
"VACUUM{}{}{}{}{}",
10640+
if self.full { " FULL" } else { "" },
10641+
if self.sort_only { " SORT ONLY" } else { "" },
10642+
if self.delete_only { " DELETE ONLY" } else { "" },
10643+
if self.reindex { " REINDEX" } else { "" },
10644+
if self.recluster { " RECLUSTER" } else { "" },
10645+
)?;
10646+
if let Some(table_name) = &self.table_name {
10647+
write!(f, " {table_name}")?;
10648+
}
10649+
if let Some(threshold) = &self.threshold {
10650+
write!(f, " TO {threshold} PERCENT")?;
10651+
}
10652+
if self.boost {
10653+
write!(f, " BOOST")?;
10654+
}
10655+
Ok(())
10656+
}
10657+
}
10658+
1060710659
#[cfg(test)]
1060810660
mod tests {
1060910661
use crate::tokenizer::Location;

‎src/ast/spans.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,7 @@ impl Spanned for Statement {
552552
),
553553
Statement::CreateUser(..) => Span::empty(),
554554
Statement::AlterSchema(s) => s.span(),
555+
Statement::Vacuum(..) => Span::empty(),
555556
}
556557
}
557558
}

‎src/keywords.rs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ define_keywords!(
144144
BLOOMFILTER,
145145
BOOL,
146146
BOOLEAN,
147+
BOOST,
147148
BOTH,
148149
BOX,
149150
BRIN,
@@ -761,6 +762,7 @@ define_keywords!(
761762
REGR_SXX,
762763
REGR_SXY,
763764
REGR_SYY,
765+
REINDEX,
764766
RELATIVE,
765767
RELAY,
766768
RELEASE,

‎src/parser/mod.rs‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,10 @@ impl<'a> Parser<'a> {
649649
self.prev_token();
650650
self.parse_export_data()
651651
}
652+
Keyword::VACUUM => {
653+
self.prev_token();
654+
self.parse_vacuum()
655+
}
652656
_ => self.expected("an SQL statement", next_token),
653657
},
654658
Token::LParen => {
@@ -16932,6 +16936,40 @@ impl<'a> Parser<'a> {
1693216936
}))
1693316937
}
1693416938

16939+
fn parse_vacuum(&mut self) -> Result<Statement, ParserError> {
16940+
self.expect_keyword(Keyword::VACUUM)?;
16941+
let full = self.parse_keyword(Keyword::FULL);
16942+
let sort_only = self.parse_keywords(&[Keyword::SORT, Keyword::ONLY]);
16943+
let delete_only = self.parse_keywords(&[Keyword::DELETE, Keyword::ONLY]);
16944+
let reindex = self.parse_keyword(Keyword::REINDEX);
16945+
let recluster = self.parse_keyword(Keyword::RECLUSTER);
16946+
let (table_name, threshold, boost) =
16947+
match self.maybe_parse(|p| p.parse_object_name(false))? {
16948+
Some(table_name) => {
16949+
let threshold = if self.parse_keyword(Keyword::TO) {
16950+
let value = self.parse_value()?;
16951+
self.expect_keyword(Keyword::PERCENT)?;
16952+
Some(value.value)
16953+
} else {
16954+
None
16955+
};
16956+
let boost = self.parse_keyword(Keyword::BOOST);
16957+
(Some(table_name), threshold, boost)
16958+
}
16959+
_ => (None, None, false),
16960+
};
16961+
Ok(Statement::Vacuum(VacuumStatement {
16962+
full,
16963+
sort_only,
16964+
delete_only,
16965+
reindex,
16966+
recluster,
16967+
table_name,
16968+
threshold,
16969+
boost,
16970+
}))
16971+
}
16972+
1693516973
/// Consume the parser and return its underlying token buffer
1693616974
pub fn into_tokens(self) -> Vec<TokenWithSpan> {
1693716975
self.tokens

‎tests/sqlparser_redshift.rs‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,3 +407,48 @@ fn parse_string_literal_backslash_escape() {
407407
fn parse_utf8_multibyte_idents() {
408408
redshift().verified_stmt("SELECT 🚀.city AS 🎸 FROM customers AS 🚀");
409409
}
410+
411+
#[test]
412+
fn parse_vacuum() {
413+
let stmt = redshift().verified_stmt("VACUUM FULL");
414+
match stmt {
415+
Statement::Vacuum(v) => {
416+
assert!(v.full);
417+
assert_eq!(v.table_name, None);
418+
}
419+
_ => unreachable!(),
420+
}
421+
let stmt = redshift().verified_stmt("VACUUM tbl");
422+
match stmt {
423+
Statement::Vacuum(v) => {
424+
assert_eq!(
425+
v.table_name,
426+
Some(ObjectName::from(vec![Ident::new("tbl"),]))
427+
);
428+
}
429+
_ => unreachable!(),
430+
}
431+
let stmt = redshift().verified_stmt(
432+
"VACUUM FULL SORT ONLY DELETE ONLY REINDEX RECLUSTER db1.sc1.tbl1 TO 20 PERCENT BOOST",
433+
);
434+
match stmt {
435+
Statement::Vacuum(v) => {
436+
assert!(v.full);
437+
assert!(v.sort_only);
438+
assert!(v.delete_only);
439+
assert!(v.reindex);
440+
assert!(v.recluster);
441+
assert_eq!(
442+
v.table_name,
443+
Some(ObjectName::from(vec![
444+
Ident::new("db1"),
445+
Ident::new("sc1"),
446+
Ident::new("tbl1"),
447+
]))
448+
);
449+
assert_eq!(v.threshold, Some(number("20")));
450+
assert!(v.boost);
451+
}
452+
_ => unreachable!(),
453+
}
454+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /