datafusion_delta_sharing/
securable.rs

1//! Delta Sharing shared object types
2
3use std::{fmt::Display, str::FromStr};
4
5use serde::{Deserialize, Serialize};
6
7use crate::error::DeltaSharingError;
8
9/// The type of a share as defined in the Delta Sharing protocol.
10///
11/// A share is a logical grouping to share with recipients. A share can be
12/// shared with one or multiple recipients. A recipient can access all
13/// resources in a share. A share may contain multiple schemas.
14#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
15#[serde(rename_all = "camelCase")]
16pub struct Share {
17    name: String,
18    id: Option<String>,
19}
20
21impl Share {
22    /// Create a new `Share` with the given `name` and `id`.
23    pub fn new<S: Into<String>>(name: S, id: Option<S>) -> Self {
24        Self {
25            name: name.into(),
26            id: id.map(Into::into),
27        }
28    }
29
30    /// Retrieve the name from `self`.
31    ///
32    /// # Example
33    ///
34    /// ```rust
35    /// use datafusion_delta_sharing::securable::Share;
36    ///
37    /// let share = Share::new("my-share", None);
38    /// assert_eq!(share.name(), "my-share");
39    /// ```
40    pub fn name(&self) -> &str {
41        self.name.as_ref()
42    }
43
44    /// Retrieve the id from `self`.
45    ///
46    /// # Example
47    ///  
48    /// ```rust
49    /// use datafusion_delta_sharing::securable::Share;
50    ///
51    /// let share = Share::new("my-share", Some("my-share-id"));
52    /// assert_eq!(share.id(), Some("my-share-id"));
53    /// ```
54    pub fn id(&self) -> Option<&str> {
55        self.id.as_deref()
56    }
57}
58
59impl Display for Share {
60    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61        write!(f, "{}", self.name())
62    }
63}
64
65impl FromStr for Share {
66    type Err = DeltaSharingError;
67
68    fn from_str(s: &str) -> Result<Self, Self::Err> {
69        Ok(Share::new(s, None))
70    }
71}
72
73/// The type of a schema as defined in the Delta Sharing protocol.
74///
75/// A schema is a logical grouping of tables. A schema may contain multiple
76/// tables. A schema is defined within the context of a [`Share`].
77#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
78#[serde(rename_all = "camelCase")]
79pub struct Schema {
80    share: String,
81    name: String,
82}
83
84impl Schema {
85    /// Create a new `Schema` with the given [`Share`], `name` and `id`.
86    pub fn new(share_name: impl Into<String>, schema_name: impl Into<String>) -> Self {
87        Self {
88            share: share_name.into(),
89            name: schema_name.into(),
90        }
91    }
92
93    /// Returns the name of the share associated with `self`
94    ///
95    /// # Example
96    ///
97    /// ```rust
98    /// use datafusion_delta_sharing::securable::{Share, Schema};
99    ///
100    /// let schema = Schema::new("my-share", "my-schema");
101    /// assert_eq!(schema.share_name(), "my-share");
102    /// ```
103    pub fn share_name(&self) -> &str {
104        self.share.as_ref()
105    }
106
107    /// Returns the name of `self`
108    ///
109    /// # Example
110    ///
111    /// ```rust
112    /// use datafusion_delta_sharing::securable::{Schema};
113    ///
114    /// let schema = Schema::new("my-share", "my-schema");
115    /// assert_eq!(schema.name(), "my-schema");
116    /// ```
117    pub fn name(&self) -> &str {
118        self.name.as_ref()
119    }
120}
121
122impl Display for Schema {
123    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
124        write!(f, "{}.{}", self.share_name(), self.name())
125    }
126}
127
128impl FromStr for Schema {
129    type Err = DeltaSharingError;
130
131    fn from_str(s: &str) -> Result<Self, Self::Err> {
132        let parts = s.split('.').collect::<Vec<_>>();
133        if parts.len() == 2 {
134            Ok(Schema::new(parts[0], parts[1]))
135        } else {
136            Err(DeltaSharingError::parse_securable(
137                "Schema must be of the form <share>.<schema>",
138            ))
139        }
140    }
141}
142
143/// The type of a table as defined in the Delta Sharing protocol.
144///
145/// A table is a Delta Lake table or a view on top of a Delta Lake table. A
146/// table is defined within the context of a [`Schema`].
147#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
148#[serde(rename_all = "camelCase")]
149pub struct Table {
150    name: String,
151    schema: String,
152    share: String,
153    share_id: Option<String>,
154    id: Option<String>,
155}
156
157impl Table {
158    /// Create a new `Table` with the given [`Schema`], `name`, `storage_path`,
159    ///  `table_id` and `table_format`. Whenever the `table_id` is `None`, it
160    /// will default to `DELTA`
161    pub fn new(
162        share_name: impl Into<String>,
163        schema_name: impl Into<String>,
164        table_name: impl Into<String>,
165        share_id: Option<String>,
166        table_id: Option<String>,
167    ) -> Self {
168        Self {
169            name: table_name.into(),
170            schema: schema_name.into(),
171            share: share_name.into(),
172            share_id,
173            id: table_id,
174        }
175    }
176
177    /// Returns the name of the share associated with `self`
178    ///
179    /// # Example
180    ///
181    /// ```rust
182    /// use datafusion_delta_sharing::securable::{Share, Schema, Table};
183    ///
184    /// let table = Table::new("my-share", "my-schema", "my-table", None, None);
185    /// assert_eq!(table.share_name(), "my-share");
186    /// ```
187    pub fn share_name(&self) -> &str {
188        self.share.as_ref()
189    }
190
191    /// Returns the id of the share associated with `self`
192    ///
193    /// # Example
194    ///
195    /// ```rust
196    /// use datafusion_delta_sharing::securable::{Share, Schema, Table};
197    ///
198    /// let table = Table::new("my-share", "my-schema", "my-table", Some("my-share-id".to_string()), None);
199    /// assert_eq!(table.share_id(), Some("my-share-id"));
200    /// ```
201    pub fn share_id(&self) -> Option<&str> {
202        self.share_id.as_deref()
203    }
204
205    /// Returns the name of the schema associated with `self`
206    ///
207    /// # Example
208    ///
209    /// ```rust
210    /// use datafusion_delta_sharing::securable::{Share, Schema, Table};
211    ///
212    /// let table = Table::new("my-share", "my-schema", "my-table", None, None);
213    /// assert_eq!(table.schema_name(), "my-schema");
214    /// ```
215    pub fn schema_name(&self) -> &str {
216        self.schema.as_ref()
217    }
218
219    /// Returns the name of `self`
220    ///
221    /// # Example
222    ///
223    /// ```rust
224    /// use datafusion_delta_sharing::securable::{Share, Schema, Table};
225    ///
226    /// let table = Table::new("my-share", "my-schema", "my-table", None, None);
227    /// assert_eq!(table.name(), "my-table");
228    /// ```
229    pub fn name(&self) -> &str {
230        self.name.as_ref()
231    }
232
233    /// Returns the id of `self`
234    ///
235    /// # Example
236    ///
237    /// ```rust
238    /// use datafusion_delta_sharing::securable::{Share, Schema, Table};
239    ///
240    /// let table = Table::new("my-share", "my-schema", "my-table", None, Some("my-table-id".to_string()));
241    /// assert_eq!(table.id(), Some("my-table-id"));
242    /// ```
243    pub fn id(&self) -> Option<&str> {
244        self.id.as_deref()
245    }
246}
247
248impl Display for Table {
249    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
250        write!(
251            f,
252            "{}.{}.{}",
253            self.share_name(),
254            self.schema_name(),
255            self.name()
256        )
257    }
258}
259
260impl FromStr for Table {
261    type Err = DeltaSharingError;
262
263    fn from_str(s: &str) -> Result<Self, Self::Err> {
264        let parts = s.split('.').collect::<Vec<_>>();
265        if parts.len() == 3 {
266            Ok(Table::new(parts[0], parts[1], parts[2], None, None))
267        } else {
268            Err(DeltaSharingError::parse_securable(
269                "Table must be of the form <share>.<schema>.<table>",
270            ))
271        }
272    }
273}
274
275#[cfg(test)]
276mod tests {
277    use super::*;
278
279    #[test]
280    fn display_share() {
281        let share = Share::new("share", Some("id"));
282        assert_eq!(format!("{}", share), "share");
283    }
284
285    #[test]
286    fn parse_share() {
287        let share = "share".parse::<Share>().unwrap();
288        assert_eq!(share, Share::new("share", None));
289    }
290
291    #[test]
292    fn display_schema() {
293        let schema = Schema::new("share", "schema");
294        assert_eq!(format!("{}", schema), "share.schema");
295    }
296
297    #[test]
298    fn parse_schema() {
299        let schema = "share.schema".parse::<Schema>().unwrap();
300        assert_eq!(schema, Schema::new("share", "schema"));
301    }
302
303    #[test]
304    fn display_table() {
305        let table = Table::new("share", "schema", "table", None, None);
306        assert_eq!(format!("{}", table), "share.schema.table");
307    }
308
309    #[test]
310    fn parse_table() {
311        let table = "share.schema.table".parse::<Table>().unwrap();
312        assert_eq!(table, Table::new("share", "schema", "table", None, None));
313    }
314}