Skip to main content

laminar_core/catalog/
mod.rs

1//! Feature-neutral catalog identity types.
2
3use serde::{Deserialize, Serialize};
4
5/// Exclusive owner of a user catalog identifier.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
7#[serde(rename_all = "snake_case")]
8pub enum CatalogObjectKind {
9    /// Ingest source.
10    Source,
11    /// Output sink.
12    Sink,
13    /// Reference table.
14    Table,
15    /// Lookup table.
16    LookupTable,
17    /// Streaming query output.
18    Stream,
19    /// Materialized streaming view.
20    MaterializedView,
21}
22
23impl std::fmt::Display for CatalogObjectKind {
24    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25        formatter.write_str(match self {
26            Self::Source => "source",
27            Self::Sink => "sink",
28            Self::Table => "table",
29            Self::LookupTable => "lookup table",
30            Self::Stream => "stream",
31            Self::MaterializedView => "materialized view",
32        })
33    }
34}
35
36/// Marker between an owner's name and a stage index in an internal stage's name.
37pub const STAGE_MARKER: &str = "$stage";
38
39/// The catalog object that owns `name` when `name` is an internal stage `<owner>$stage<n>`: a
40/// hidden stream the planner splits out of the owner's query, whose state belongs to the owner.
41#[must_use]
42pub fn stage_owner(name: &str) -> Option<&str> {
43    let (owner, index) = name.rsplit_once(STAGE_MARKER)?;
44    (!owner.is_empty() && !index.is_empty() && index.bytes().all(|byte| byte.is_ascii_digit()))
45        .then_some(owner)
46}
47
48#[cfg(test)]
49mod tests {
50    use super::stage_owner;
51
52    #[test]
53    fn stage_names_round_trip_to_their_owner() {
54        assert_eq!(stage_owner("out$stage1"), Some("out"));
55        assert_eq!(stage_owner("a$stage2$stage12"), Some("a$stage2"));
56        for name in ["out", "$stage1", "out$stage", "out$stagex", "out$stage1a"] {
57            assert_eq!(stage_owner(name), None, "{name}");
58        }
59    }
60}