iceberg_rust/catalog/
tabular.rs

1/*!
2 * Provides the [Relation] enum to refer to any queriable entity like a table or a view
3*/
4
5use std::sync::Arc;
6
7use iceberg_rust_spec::spec::tabular::TabularMetadata;
8use object_store::ObjectStore;
9
10use crate::error::Error;
11use crate::materialized_view::MaterializedView;
12use crate::table::Table;
13use crate::view::View;
14
15use super::identifier::Identifier;
16use super::Catalog;
17
18#[derive(Debug, Clone)]
19#[allow(clippy::large_enum_variant)]
20/// Enum for different types that can be queried like a table, for example view
21pub enum Tabular {
22    /// An iceberg table
23    Table(Table),
24    /// An iceberg view
25    View(View),
26    /// An iceberg materialized view
27    MaterializedView(MaterializedView),
28}
29
30impl Tabular {
31    #[inline]
32    /// Return metadata location for relation.
33    pub fn identifier(&self) -> &Identifier {
34        match self {
35            Tabular::Table(table) => table.identifier(),
36            Tabular::View(view) => view.identifier(),
37            Tabular::MaterializedView(mv) => mv.identifier(),
38        }
39    }
40
41    #[inline]
42    /// Return metadata location for relation.
43    pub fn metadata(&self) -> TabularMetadata {
44        match self {
45            Tabular::Table(table) => TabularMetadata::Table(table.metadata().clone()),
46            Tabular::View(view) => TabularMetadata::View(view.metadata().clone()),
47            Tabular::MaterializedView(mv) => {
48                TabularMetadata::MaterializedView(mv.metadata().clone())
49            }
50        }
51    }
52
53    #[inline]
54    /// Return catalog for relation.
55    pub fn catalog(&self) -> Arc<dyn Catalog> {
56        match self {
57            Tabular::Table(table) => table.catalog(),
58            Tabular::View(view) => view.catalog(),
59            Tabular::MaterializedView(mv) => mv.catalog(),
60        }
61    }
62
63    /// Reload relation from catalog
64    pub async fn reload(&mut self) -> Result<(), Error> {
65        match self {
66            Tabular::Table(table) => {
67                let new = if let Tabular::Table(table) =
68                    table.catalog().load_tabular(table.identifier()).await?
69                {
70                    Ok(table)
71                } else {
72                    Err(Error::InvalidFormat(
73                        "Tabular type from catalog response".to_string(),
74                    ))
75                }?;
76                let _ = std::mem::replace(table, new);
77            }
78            Tabular::View(view) => {
79                let new = if let Tabular::View(view) =
80                    view.catalog().load_tabular(view.identifier()).await?
81                {
82                    Ok(view)
83                } else {
84                    Err(Error::InvalidFormat(
85                        "Tabular type from catalog response".to_string(),
86                    ))
87                }?;
88                let _ = std::mem::replace(view, new);
89            }
90            Tabular::MaterializedView(matview) => {
91                let new = if let Tabular::MaterializedView(matview) =
92                    matview.catalog().load_tabular(matview.identifier()).await?
93                {
94                    Ok(matview)
95                } else {
96                    Err(Error::InvalidFormat(
97                        "Tabular type from catalog response".to_string(),
98                    ))
99                }?;
100                let _ = std::mem::replace(matview, new);
101            }
102        };
103        Ok(())
104    }
105}
106
107/// Fetch metadata of a tabular(table, view, materialized view) structure from an object_store
108pub async fn get_tabular_metadata(
109    metadata_location: &str,
110    object_store: Arc<dyn ObjectStore>,
111) -> Result<TabularMetadata, Error> {
112    let bytes = object_store
113        .get(&metadata_location.into())
114        .await?
115        .bytes()
116        .await?;
117    Ok(serde_json::from_slice(&bytes)?)
118}