vendor/iceberg-arrow59/src/transaction/update_partition_spec.rs
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//! Partition spec evolution as a transaction action (skade patch, 2026-10-17):
//! `TableUpdate::AddSpec` + `TableUpdate::SetDefaultSpec` existed only at the
//! catalog level; this is the action a caller reaches through
//! [`Transaction::add_partition_spec`](crate::transaction::Transaction::add_partition_spec).
//! The table's existing data files keep their spec (unpartitioned files of
//! spec 0 are read as before); files written after the commit carry the new
//! spec, and a rewrite of the old files moves them over.
use std::sync::Arc;
use async_trait::async_trait;
use crate::spec::{TableMetadataBuilder, UnboundPartitionSpec};
use crate::table::Table;
use crate::transaction::action::{ActionCommit, TransactionAction};
use crate::{Result, TableRequirement, TableUpdate};
/// Add a partition spec to a table, and make it the default unless
/// [`keep_default`](Self::keep_default) says otherwise.
pub struct AddPartitionSpecAction {
spec: UnboundPartitionSpec,
set_default: bool,
}
impl AddPartitionSpecAction {
pub(crate) fn new(spec: UnboundPartitionSpec) -> Self {
Self { spec, set_default: true }
}
/// Add the spec without making it the default (default: make it the default).
pub fn keep_default(mut self) -> Self {
self.set_default = false;
self
}
}
#[async_trait]
impl TransactionAction for AddPartitionSpecAction {
async fn commit(self: Arc<Self>, table: &Table) -> Result<ActionCommit> {
let metadata = table.metadata();
let mut updates = vec![TableUpdate::AddSpec { spec: self.spec.clone() }];
if self.set_default {
updates.push(TableUpdate::SetDefaultSpec { spec_id: TableMetadataBuilder::LAST_ADDED });
}
Ok(ActionCommit::new(updates, vec![
TableRequirement::UuidMatch { uuid: metadata.uuid() },
TableRequirement::DefaultSpecIdMatch { default_spec_id: metadata.default_partition_spec_id() },
]))
}
}