Skip to content

Commit 3a9f404

Browse files
authored
feat: support vacuum leaked table data (#17022)
* feat: support vacuum leaked table data * regen golden file
1 parent 811c639 commit 3a9f404

File tree

6 files changed

+81
-2
lines changed

6 files changed

+81
-2
lines changed

src/query/ast/src/ast/statements/table.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,7 @@ pub struct VacuumDropTableOption {
774774
// Some(true) means dry run with summary option
775775
pub dry_run: Option<bool>,
776776
pub limit: Option<usize>,
777+
pub force: bool,
777778
}
778779

779780
impl Display for VacuumDropTableOption {
@@ -787,6 +788,9 @@ impl Display for VacuumDropTableOption {
787788
if let Some(limit) = self.limit {
788789
write!(f, " LIMIT {}", limit)?;
789790
}
791+
if self.force {
792+
write!(f, " FORCE")?;
793+
}
790794
Ok(())
791795
}
792796
}

src/query/ast/src/parser/statement.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3777,11 +3777,12 @@ pub fn literal_duration(i: Input) -> IResult<Duration> {
37773777
pub fn vacuum_drop_table_option(i: Input) -> IResult<VacuumDropTableOption> {
37783778
alt((map(
37793779
rule! {
3780-
(DRY ~ ^RUN ~ SUMMARY?)? ~ (LIMIT ~ #literal_u64)?
3780+
(DRY ~ ^RUN ~ SUMMARY?)? ~ (LIMIT ~ #literal_u64)? ~ FORCE?
37813781
},
3782-
|(opt_dry_run, opt_limit)| VacuumDropTableOption {
3782+
|(opt_dry_run, opt_limit, opt_force)| VacuumDropTableOption {
37833783
dry_run: opt_dry_run.map(|dry_run| dry_run.2.is_some()),
37843784
limit: opt_limit.map(|(_, limit)| limit as usize),
3785+
force: opt_force.is_some(),
37853786
},
37863787
),))(i)
37873788
}

src/query/ast/tests/it/testdata/stmt.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13016,6 +13016,7 @@ VacuumDropTable(
1301613016
option: VacuumDropTableOption {
1301713017
dry_run: None,
1301813018
limit: None,
13019+
force: false,
1301913020
},
1302013021
},
1302113022
)
@@ -13035,6 +13036,7 @@ VacuumDropTable(
1303513036
false,
1303613037
),
1303713038
limit: None,
13039+
force: false,
1303813040
},
1303913041
},
1304013042
)
@@ -13054,6 +13056,7 @@ VacuumDropTable(
1305413056
true,
1305513057
),
1305613058
limit: None,
13059+
force: false,
1305713060
},
1305813061
},
1305913062
)
@@ -13080,6 +13083,7 @@ VacuumDropTable(
1308013083
option: VacuumDropTableOption {
1308113084
dry_run: None,
1308213085
limit: None,
13086+
force: false,
1308313087
},
1308413088
},
1308513089
)
@@ -13108,6 +13112,7 @@ VacuumDropTable(
1310813112
limit: Some(
1310913113
10,
1311013114
),
13115+
force: false,
1311113116
},
1311213117
},
1311313118
)

src/query/service/src/interpreters/interpreter_vacuum_drop_tables.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@ use databend_common_meta_app::schema::DroppedId;
3131
use databend_common_meta_app::schema::GcDroppedTableReq;
3232
use databend_common_meta_app::schema::ListDroppedTableReq;
3333
use databend_common_sql::plans::VacuumDropTablePlan;
34+
use databend_common_storage::DataOperator;
3435
use databend_common_storages_view::view_table::VIEW_ENGINE;
3536
use databend_enterprise_vacuum_handler::get_vacuum_handler;
37+
use futures_util::TryStreamExt;
3638
use log::info;
3739

3840
use crate::interpreters::Interpreter;
@@ -116,6 +118,11 @@ impl Interpreter for VacuumDropTablesInterpreter {
116118
LicenseManagerSwitch::instance()
117119
.check_enterprise_enabled(self.ctx.get_license_key(), Vacuum)?;
118120

121+
if self.plan.option.force {
122+
self.vacuum_drop_tables_force().await?;
123+
return Ok(PipelineBuildResult::create());
124+
}
125+
119126
let ctx = self.ctx.clone();
120127
let duration = Duration::days(ctx.get_settings().get_data_retention_time_in_days()? as i64);
121128

@@ -133,6 +140,7 @@ impl Interpreter for VacuumDropTablesInterpreter {
133140
};
134141

135142
let tenant = self.ctx.get_tenant();
143+
136144
let (tables, drop_ids) = catalog
137145
.get_drop_table_infos(ListDroppedTableReq::new4(
138146
&tenant,
@@ -275,3 +283,62 @@ impl Interpreter for VacuumDropTablesInterpreter {
275283
}
276284
}
277285
}
286+
287+
impl VacuumDropTablesInterpreter {
288+
async fn vacuum_drop_tables_force(&self) -> Result<()> {
289+
let catalog = self.ctx.get_catalog(self.plan.catalog.as_str()).await?;
290+
let op = DataOperator::instance().operator();
291+
let databases = match self.plan.database.is_empty() {
292+
true => catalog.list_databases(&self.ctx.get_tenant()).await?,
293+
false => {
294+
let database = catalog
295+
.get_database(&self.ctx.get_tenant(), &self.plan.database)
296+
.await?;
297+
vec![database]
298+
}
299+
};
300+
301+
for database in databases {
302+
if database.name() == "system" || database.name() == "information_schema" {
303+
continue;
304+
}
305+
let db_id = database.get_db_info().database_id.db_id;
306+
info!(
307+
"vacuum drop table force from db name: {}, id: {}",
308+
database.name(),
309+
db_id
310+
);
311+
let mut lister = op.lister_with(&db_id.to_string()).recursive(true).await?;
312+
let mut paths = vec![];
313+
let mut orphan_paths = vec![];
314+
while let Some(entry) = lister.try_next().await? {
315+
paths.push(entry.path().to_string());
316+
}
317+
let tables_in_meta = database.list_tables_history().await?;
318+
let table_ids_in_meta = tables_in_meta
319+
.iter()
320+
.map(|t| t.get_id())
321+
.collect::<HashSet<_>>();
322+
for path in paths {
323+
let Some(table_id) = path.split('/').nth(1) else {
324+
info!("can not parse table id from path: {}", path);
325+
continue;
326+
};
327+
let Some(table_id) = table_id.parse::<u64>().ok() else {
328+
info!("can not parse table id from path: {}", path);
329+
continue;
330+
};
331+
if !table_ids_in_meta.contains(&table_id) {
332+
orphan_paths.push(path);
333+
}
334+
}
335+
info!(
336+
"orphan_paths summary: {:?}",
337+
orphan_paths.iter().take(100).collect::<Vec<_>>()
338+
);
339+
op.remove(orphan_paths).await?;
340+
}
341+
342+
Ok(())
343+
}
344+
}

src/query/sql/src/planner/binder/ddl/table.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1271,6 +1271,7 @@ impl Binder {
12711271
VacuumDropTableOption {
12721272
dry_run: option.dry_run,
12731273
limit: option.limit,
1274+
force: option.force,
12741275
}
12751276
};
12761277
Ok(Plan::VacuumDropTable(Box::new(VacuumDropTablePlan {

src/query/sql/src/planner/plans/ddl/table.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ pub struct VacuumDropTableOption {
188188
// Some(true) means dry run with summary option
189189
pub dry_run: Option<bool>,
190190
pub limit: Option<usize>,
191+
pub force: bool,
191192
}
192193

193194
#[derive(Debug, Clone)]

0 commit comments

Comments
 (0)