iceberg_rust/view/
mod.rs

1//! View management for Apache Iceberg tables
2//!
3//! This module provides the core functionality for working with Iceberg views:
4//!
5//! - Creating and managing views through the [View] struct
6//! - Atomic updates via [transaction] support
7//! - Schema evolution and versioning
8//! - View metadata management
9//! - Integration with catalogs and object stores
10//!
11//! Views provide a logical abstraction over underlying data, supporting:
12//! - SQL-based view definitions
13//! - Schema evolution tracking
14//! - Version history
15//! - Properties and configuration
16//! - Metadata management
17//!
18//! # Example
19//! ```rust,no_run
20//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
21//! use iceberg_rust::view::View;
22//!
23//! // Create a new view using the builder pattern
24//! let mut view = View::builder()
25//!     .with_name("example_view")
26//!     .with_schema(/* ... */)
27//!     .build()
28//!     .await?;
29//!
30//! // Start a transaction to update the view
31//! view.new_transaction(None)
32//!     .update_properties(vec![("comment".into(), "Example view".into())])
33//!     .commit()
34//!     .await?;
35//! # Ok(())
36//! # }
37//! ```
38
39use std::sync::Arc;
40
41use iceberg_rust_spec::spec::{schema::Schema, view_metadata::ViewMetadata};
42use object_store::ObjectStore;
43
44use crate::{
45    catalog::{create::CreateViewBuilder, identifier::Identifier, Catalog},
46    error::Error,
47    object_store::Bucket,
48};
49
50use self::transaction::Transaction as ViewTransaction;
51
52pub mod transaction;
53
54#[derive(Debug, Clone)]
55/// An Iceberg view provides a logical view over underlying data with schema evolution and versioning
56///
57/// Views store:
58/// - SQL query or other representation of the view logic
59/// - Schema evolution history
60/// - Version history for view definitions
61/// - Properties for configuration
62/// - Metadata about view location and catalog
63///
64/// Views can be either filesystem-based or managed by a metastore catalog.
65/// They support transactions for atomic updates to their definition and properties.
66///
67/// The View struct provides the main interface for:
68/// - Creating and managing views
69/// - Accessing view metadata and schemas
70/// - Starting transactions for atomic updates
71/// - Interacting with the underlying storage system
72pub struct View {
73    /// Type of the View, either filesystem or metastore.
74    identifier: Identifier,
75    /// Metadata for the iceberg view according to the iceberg view spec
76    metadata: ViewMetadata,
77    /// Catalog of the table
78    catalog: Arc<dyn Catalog>,
79}
80
81/// Public interface of the table.
82impl View {
83    /// Creates a new builder for configuring and creating an Iceberg view
84    ///
85    /// Returns a `CreateViewBuilder` that provides a fluent interface for:
86    /// - Setting the view name and location
87    /// - Configuring view properties
88    /// - Defining the view schema
89    /// - Setting SQL or other view representations
90    /// - Specifying the catalog and namespace
91    ///
92    /// # Returns
93    /// * `CreateViewBuilder<Option<()>>` - A builder for creating new views
94    pub fn builder() -> CreateViewBuilder<Option<()>> {
95        CreateViewBuilder::default()
96    }
97    /// Creates a new Iceberg view instance with the given identifier, catalog and metadata
98    ///
99    /// # Arguments
100    /// * `identifier` - The unique identifier for this view in the catalog
101    /// * `catalog` - The catalog that will manage this view
102    /// * `metadata` - The view metadata containing schema, versions, and other view information
103    ///
104    /// # Returns
105    /// * `Result<Self, Error>` - The new view instance or an error if creation fails
106    ///
107    /// This is typically called by catalog implementations rather than directly by users.
108    /// For creating new views, use the `builder()` method instead.
109    pub async fn new(
110        identifier: Identifier,
111        catalog: Arc<dyn Catalog>,
112        metadata: ViewMetadata,
113    ) -> Result<Self, Error> {
114        Ok(View {
115            identifier,
116            metadata,
117            catalog,
118        })
119    }
120    /// Gets the unique identifier for this view in the catalog
121    ///
122    /// The identifier contains:
123    /// - The namespace path for the view
124    /// - The view name
125    ///
126    /// # Returns
127    /// * `&Identifier` - A reference to this view's identifier
128    pub fn identifier(&self) -> &Identifier {
129        &self.identifier
130    }
131    /// Gets the catalog that manages this view
132    ///
133    /// The catalog handles:
134    /// - View metadata storage and retrieval
135    /// - Schema management
136    /// - View versioning
137    /// - Access control
138    ///
139    /// # Returns
140    /// * `Arc<dyn Catalog>` - A thread-safe reference to the catalog
141    pub fn catalog(&self) -> Arc<dyn Catalog> {
142        self.catalog.clone()
143    }
144    /// Gets the object store for this view's storage location
145    ///
146    /// The object store provides:
147    /// - Access to the underlying storage system (S3, local filesystem, etc)
148    /// - Read/write operations for view data and metadata
149    /// - Storage-specific configuration and credentials
150    ///
151    /// # Returns
152    /// * `Arc<dyn ObjectStore>` - A thread-safe reference to the configured object store
153    pub fn object_store(&self) -> Arc<dyn ObjectStore> {
154        self.catalog
155            .object_store(Bucket::from_path(&self.metadata.location).unwrap())
156    }
157    /// Gets the current schema for this view, optionally for a specific branch
158    ///
159    /// # Arguments
160    /// * `branch` - Optional branch name to get the schema for. If None, returns the main branch schema
161    ///
162    /// # Returns
163    /// * `Result<&Schema, Error>` - The current schema for the view/branch, or an error if not found
164    ///
165    /// The schema defines the structure of the view's output, including:
166    /// - Column names and types
167    /// - Column IDs and documentation
168    /// - Whether columns are required/optional
169    pub fn current_schema(&self, branch: Option<&str>) -> Result<&Schema, Error> {
170        self.metadata.current_schema(branch).map_err(Error::from)
171    }
172    /// Gets the underlying view metadata that defines this view
173    ///
174    /// The metadata contains:
175    /// - View UUID and format version
176    /// - Storage location information
177    /// - Version history and schema evolution
178    /// - View properties and configurations
179    /// - SQL representations and other view definitions
180    ///
181    /// # Returns
182    /// * `&ViewMetadata` - A reference to the view's metadata
183    pub fn metadata(&self) -> &ViewMetadata {
184        &self.metadata
185    }
186    /// Creates a new transaction for performing atomic updates to this view
187    ///
188    /// # Arguments
189    /// * `branch` - Optional branch name to create the transaction for. If None, uses the main branch
190    ///
191    /// # Returns
192    /// * `ViewTransaction` - A new transaction that can be used to:
193    ///   - Update view representations and schemas
194    ///   - Modify view properties
195    ///   - Commit changes atomically
196    ///
197    /// Transactions ensure that all changes are applied atomically with ACID guarantees.
198    /// Multiple operations can be chained and will be committed together.
199    pub fn new_transaction(&mut self, branch: Option<&str>) -> ViewTransaction {
200        ViewTransaction::new(self, branch)
201    }
202}