Skip to main content

radixdb_core/
identity.rs

1//! Runtime identities bound to one schema generation.
2
3/// Create opaque time-ordered bytes for a durable higher-layer identity.
4///
5/// Core deliberately does not attach catalog or artifact semantics to these
6/// bytes. Owners in sibling crates apply their own reserved-range admission.
7#[doc(hidden)]
8pub fn new_durable_identity_bytes() -> [u8; 16] {
9    uuid::Uuid::now_v7().into_bytes()
10}
11
12/// Runtime-stable identity of a table inside one engine schema generation.
13///
14/// The identity is intentionally not persisted. Any DDL changes the schema
15/// generation and invalidates previously bound identities; reopen builds a new
16/// engine scope and callers bind again from the durable schema catalog.
17#[derive(Debug, Clone, PartialEq, Eq, Hash)]
18pub struct SchemaTableId {
19    scope_id: u64,
20    schema_generation: u64,
21    table_name_lower: String,
22}
23
24impl SchemaTableId {
25    /// Construct an identity after authoritative schema binding.
26    ///
27    /// This is public only because the storage owner lives in a sibling crate.
28    /// Applications must obtain identities through the engine binding API.
29    #[doc(hidden)]
30    pub fn new(scope_id: u64, schema_generation: u64, table_name_lower: String) -> Self {
31        Self {
32            scope_id,
33            schema_generation,
34            table_name_lower,
35        }
36    }
37
38    pub fn scope_id(&self) -> u64 {
39        self.scope_id
40    }
41
42    pub fn schema_generation(&self) -> u64 {
43        self.schema_generation
44    }
45
46    pub fn table_name(&self) -> &str {
47        &self.table_name_lower
48    }
49}
50
51/// Runtime-stable identity of a column inside one bound table generation.
52#[derive(Debug, Clone, PartialEq, Eq, Hash)]
53pub struct SchemaColumnId {
54    table: SchemaTableId,
55    ordinal: usize,
56}
57
58impl SchemaColumnId {
59    /// Construct an identity after authoritative column binding.
60    ///
61    /// This is public only because the storage owner lives in a sibling crate.
62    /// Applications must obtain identities through the engine binding API.
63    #[doc(hidden)]
64    pub fn new(table: SchemaTableId, ordinal: usize) -> Self {
65        Self { table, ordinal }
66    }
67
68    pub fn table(&self) -> &SchemaTableId {
69        &self.table
70    }
71
72    pub fn ordinal(&self) -> usize {
73        self.ordinal
74    }
75}
76
77#[cfg(test)]
78mod tests {
79    use super::*;
80
81    #[test]
82    fn identities_preserve_scope_generation_name_and_ordinal() {
83        let table = SchemaTableId::new(7, 11, "users".to_owned());
84        let column = SchemaColumnId::new(table.clone(), 3);
85
86        assert_eq!(table.scope_id(), 7);
87        assert_eq!(table.schema_generation(), 11);
88        assert_eq!(table.table_name(), "users");
89        assert_eq!(column.table(), &table);
90        assert_eq!(column.ordinal(), 3);
91    }
92
93    #[test]
94    fn durable_identity_bytes_are_uuid_v7_and_distinct() {
95        let first = new_durable_identity_bytes();
96        let second = new_durable_identity_bytes();
97        assert_ne!(first, second);
98        assert_eq!(first[6] >> 4, 7);
99        assert_eq!(second[6] >> 4, 7);
100    }
101}