crates/iceberg/src/transaction/sort_order.rs (16 lines of code) (raw):

// 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. use crate::error::Result; use crate::spec::{NullOrder, SortDirection, SortField, SortOrder, Transform}; use crate::transaction::Transaction; use crate::{Error, ErrorKind, TableRequirement, TableUpdate}; /// Transaction action for replacing sort order. pub struct ReplaceSortOrderAction<'a> { pub tx: Transaction<'a>, pub sort_fields: Vec<SortField>, } impl<'a> ReplaceSortOrderAction<'a> { /// Adds a field for sorting in ascending order. pub fn asc(self, name: &str, null_order: NullOrder) -> Result<Self> { self.add_sort_field(name, SortDirection::Ascending, null_order) } /// Adds a field for sorting in descending order. pub fn desc(self, name: &str, null_order: NullOrder) -> Result<Self> { self.add_sort_field(name, SortDirection::Descending, null_order) } /// Finished building the action and apply it to the transaction. pub fn apply(mut self) -> Result<Transaction<'a>> { let unbound_sort_order = SortOrder::builder() .with_fields(self.sort_fields) .build_unbound()?; let updates = vec![ TableUpdate::AddSortOrder { sort_order: unbound_sort_order, }, TableUpdate::SetDefaultSortOrder { sort_order_id: -1 }, ]; let requirements = vec![ TableRequirement::CurrentSchemaIdMatch { current_schema_id: self .tx .current_table .metadata() .current_schema() .schema_id(), }, TableRequirement::DefaultSortOrderIdMatch { default_sort_order_id: self .tx .current_table .metadata() .default_sort_order() .order_id, }, ]; self.tx.apply(updates, requirements)?; Ok(self.tx) } fn add_sort_field( mut self, name: &str, sort_direction: SortDirection, null_order: NullOrder, ) -> Result<Self> { let field_id = self .tx .current_table .metadata() .current_schema() .field_id_by_name(name) .ok_or_else(|| { Error::new( ErrorKind::DataInvalid, format!("Cannot find field {} in table schema", name), ) })?; let sort_field = SortField::builder() .source_id(field_id) .transform(Transform::Identity) .direction(sort_direction) .null_order(null_order) .build(); self.sort_fields.push(sort_field); Ok(self) } } #[cfg(test)] mod tests { use crate::transaction::tests::make_v2_table; use crate::transaction::Transaction; use crate::{TableRequirement, TableUpdate}; #[test] fn test_replace_sort_order() { let table = make_v2_table(); let tx = Transaction::new(&table); let tx = tx.replace_sort_order().apply().unwrap(); assert_eq!( vec![ TableUpdate::AddSortOrder { sort_order: Default::default() }, TableUpdate::SetDefaultSortOrder { sort_order_id: -1 } ], tx.updates ); assert_eq!( vec![ TableRequirement::CurrentSchemaIdMatch { current_schema_id: 1 }, TableRequirement::DefaultSortOrderIdMatch { default_sort_order_id: 3 } ], tx.requirements ); } }