Skip to content

Commit 1dabf72

Browse files
committed
feat(table): add compact fns + binding
1 parent 0dca5ce commit 1dabf72

3 files changed

Lines changed: 38 additions & 2 deletions

File tree

bindings/python/python/pypaimon_rust/datafusion.pyi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ class Table:
6161
def expire_snapshots(self, older_than_ms: int) -> int: ...
6262
def remove_orphan_files(self) -> int: ...
6363
def drop_partition(self, partition: Dict[str, Any]) -> None: ...
64+
def trigger_compaction(self, full_compact: bool) -> None: ...
6465

6566
class PaimonCatalog:
6667
def __init__(self, catalog_options: Dict[str, str]) -> None: ...

bindings/python/src/table.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,9 @@ impl PyTable {
113113
})
114114
}
115115

116-
fn trigger_compaction(&self, _full_compact: bool) -> PyResult<()> {
117-
todo!()
116+
fn trigger_compaction(&self, py: Python<'_>, full_compact: bool) -> PyResult<()> {
117+
let _ = full_compact;
118+
let rt = runtime();
119+
py.detach(|| rt.block_on(async { self.inner.full_compact().await.map_err(to_py_err) }))
118120
}
119121
}

crates/paimon/src/table/mod.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,39 @@ impl Table {
196196
WriteBuilder::new(self)
197197
}
198198

199+
// Perform full compaction by scanning live data. Merge + dedup happen during scan.
200+
// Than rewrite it through dynamic OVERWRITE.
201+
//
202+
// This is whole table operation. When called, it will scan and potentially overwrite all partitions and buckets.
203+
// Use with caution.
204+
pub async fn full_compaction(&self) -> Result<()> {
205+
use futures::StreamExt;
206+
let read_builder = self.new_read_builder();
207+
let splits = read_builder.new_scan().plan().await?.splits().to_vec();
208+
if splits.is_empty() {
209+
return Ok(());
210+
}
211+
let read = read_builder.new_read()?;
212+
let mut stream = read.to_arrow(&splits)?;
213+
let mut write = self.new_write_builder().with_overwrite().new_write()?;
214+
let mut wrote_any = false;
215+
while let Some(batch) = stream.next().await {
216+
let batch = batch?;
217+
if batch.num_rows() == 0 {
218+
continue;
219+
}
220+
write.write_arrow_batch(&batch).await?;
221+
wrote_any = true;
222+
}
223+
if !wrote_any {
224+
return Ok(());
225+
}
226+
let msgs = write.prepare_commit().await?;
227+
let commit = self.new_write_builder().new_commit();
228+
// None partitions are used for dynamic overwrite.
229+
commit.overwrite(msgs, None).await
230+
}
231+
199232
/// Create a copy of this table with extra options merged into the schema.
200233
///
201234
/// This never switches the schema version; it corresponds to Java

0 commit comments

Comments
 (0)