1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4use use_db_name::{CollectionName, ConstraintName, DatabaseName, IndexName, SchemaName, TableName};
7
8#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
10pub struct SchemaRef {
11 database: Option<DatabaseName>,
12 schema: SchemaName,
13}
14
15impl SchemaRef {
16 #[must_use]
18 pub const fn new(schema: SchemaName) -> Self {
19 Self {
20 database: None,
21 schema,
22 }
23 }
24
25 #[must_use]
27 pub fn with_database(mut self, database: DatabaseName) -> Self {
28 self.database = Some(database);
29 self
30 }
31
32 #[must_use]
34 pub const fn database(&self) -> Option<&DatabaseName> {
35 self.database.as_ref()
36 }
37
38 #[must_use]
40 pub const fn schema(&self) -> &SchemaName {
41 &self.schema
42 }
43}
44
45#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
47pub enum SchemaObject {
48 Table(TableName),
50 Collection(CollectionName),
52 Index(IndexName),
54 Constraint(ConstraintName),
56 Other(String),
58}
59
60#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
62pub struct SchemaVersion(String);
63
64impl SchemaVersion {
65 #[must_use]
67 pub fn new(version: impl Into<String>) -> Self {
68 Self(version.into())
69 }
70
71 #[must_use]
73 pub fn as_str(&self) -> &str {
74 &self.0
75 }
76}
77
78#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
80pub struct SchemaNamespace {
81 schemas: Vec<SchemaName>,
82}
83
84impl SchemaNamespace {
85 #[must_use]
87 pub const fn new(schemas: Vec<SchemaName>) -> Self {
88 Self { schemas }
89 }
90
91 #[must_use]
93 pub fn schemas(&self) -> &[SchemaName] {
94 &self.schemas
95 }
96
97 #[must_use]
99 pub fn is_empty(&self) -> bool {
100 self.schemas.is_empty()
101 }
102}
103
104#[derive(Clone, Debug, Eq, PartialEq)]
106pub struct SchemaMetadata {
107 reference: SchemaRef,
108 version: Option<SchemaVersion>,
109 objects: Vec<SchemaObject>,
110}
111
112impl SchemaMetadata {
113 #[must_use]
115 pub const fn new(reference: SchemaRef) -> Self {
116 Self {
117 reference,
118 version: None,
119 objects: Vec::new(),
120 }
121 }
122
123 #[must_use]
125 pub fn with_version(mut self, version: SchemaVersion) -> Self {
126 self.version = Some(version);
127 self
128 }
129
130 #[must_use]
132 pub fn with_objects(mut self, objects: Vec<SchemaObject>) -> Self {
133 self.objects = objects;
134 self
135 }
136
137 #[must_use]
139 pub const fn reference(&self) -> &SchemaRef {
140 &self.reference
141 }
142
143 #[must_use]
145 pub const fn version(&self) -> Option<&SchemaVersion> {
146 self.version.as_ref()
147 }
148
149 #[must_use]
151 pub fn objects(&self) -> &[SchemaObject] {
152 &self.objects
153 }
154}
155
156#[cfg(test)]
157mod tests {
158 use super::{SchemaMetadata, SchemaNamespace, SchemaObject, SchemaRef, SchemaVersion};
159 use use_db_name::{DatabaseName, SchemaName, TableName};
160
161 #[test]
162 fn stores_schema_metadata() -> Result<(), Box<dyn std::error::Error>> {
163 let schema = SchemaName::new("public")?;
164 let reference = SchemaRef::new(schema.clone()).with_database(DatabaseName::new("app")?);
165 let metadata = SchemaMetadata::new(reference).with_version(SchemaVersion::new("1"));
166 let namespace = SchemaNamespace::new(vec![schema]);
167
168 assert_eq!(
169 metadata.reference().database().expect("database").as_str(),
170 "app"
171 );
172 assert_eq!(metadata.version().expect("version").as_str(), "1");
173 assert!(!namespace.is_empty());
174 assert_eq!(
175 SchemaObject::Table(TableName::new("users")?),
176 SchemaObject::Table(TableName::new("users")?)
177 );
178 Ok(())
179 }
180}