diff --git a/crates/deltalake-core/src/operations/delete.rs b/crates/deltalake-core/src/operations/delete.rs index 35cf0b858f..7ee70a3a63 100644 --- a/crates/deltalake-core/src/operations/delete.rs +++ b/crates/deltalake-core/src/operations/delete.rs @@ -275,6 +275,8 @@ impl std::future::IntoFuture for DeleteBuilder { let mut this = self; Box::pin(async move { + PROTOCOL.check_append_only(&this.snapshot)?; + PROTOCOL.can_write_to(&this.snapshot)?; let state = this.state.unwrap_or_else(|| { diff --git a/crates/deltalake-core/src/operations/transaction/protocol.rs b/crates/deltalake-core/src/operations/transaction/protocol.rs index 47e4d0a41a..a0ce1df64e 100644 --- a/crates/deltalake-core/src/operations/transaction/protocol.rs +++ b/crates/deltalake-core/src/operations/transaction/protocol.rs @@ -68,6 +68,14 @@ impl ProtocolChecker { 2 } + /// Check append-only at the high level (operation level) + pub fn check_append_only(&self, snapshot: &DeltaTableState) -> Result<(), TransactionError> { + if snapshot.table_config().append_only() { + return Err(TransactionError::DeltaTableAppendOnly); + } + Ok(()) + } + /// Check if delta-rs can read form the given delta table. pub fn can_read_from(&self, snapshot: &DeltaTableState) -> Result<(), TransactionError> { let required_features: Option<&HashSet> = diff --git a/crates/deltalake-core/src/operations/update.rs b/crates/deltalake-core/src/operations/update.rs index fa44724beb..45d0306697 100644 --- a/crates/deltalake-core/src/operations/update.rs +++ b/crates/deltalake-core/src/operations/update.rs @@ -428,6 +428,8 @@ impl std::future::IntoFuture for UpdateBuilder { let mut this = self; Box::pin(async move { + PROTOCOL.check_append_only(&this.snapshot)?; + PROTOCOL.can_write_to(&this.snapshot)?; let state = this.state.unwrap_or_else(|| { diff --git a/crates/deltalake-core/src/operations/write.rs b/crates/deltalake-core/src/operations/write.rs index 8fd8ddd99e..7f61e46c5c 100644 --- a/crates/deltalake-core/src/operations/write.rs +++ b/crates/deltalake-core/src/operations/write.rs @@ -371,6 +371,10 @@ impl std::future::IntoFuture for WriteBuilder { let mut this = self; Box::pin(async move { + if this.mode == SaveMode::Overwrite { + PROTOCOL.check_append_only(&this.snapshot)?; + } + // Create table actions to initialize table in case it does not yet exist and should be created let mut actions = this.check_preconditions().await?; diff --git a/crates/deltalake-core/src/protocol/mod.rs b/crates/deltalake-core/src/protocol/mod.rs index 264a45eb8b..56edde7f78 100644 --- a/crates/deltalake-core/src/protocol/mod.rs +++ b/crates/deltalake-core/src/protocol/mod.rs @@ -578,7 +578,7 @@ impl DeltaOperation { } /// The SaveMode used when performing a DeltaOperation -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] pub enum SaveMode { /// Files will be appended to the target location. Append,