1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4use use_db_name::{ColumnName, IndexName, TableName};
7
8#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
10pub struct IndexRef {
11 name: Option<IndexName>,
12 table: Option<TableName>,
13}
14
15impl IndexRef {
16 #[must_use]
18 pub const fn new(name: Option<IndexName>, table: Option<TableName>) -> Self {
19 Self { name, table }
20 }
21
22 #[must_use]
24 pub const fn name(&self) -> Option<&IndexName> {
25 self.name.as_ref()
26 }
27
28 #[must_use]
30 pub const fn table(&self) -> Option<&TableName> {
31 self.table.as_ref()
32 }
33}
34
35#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
37pub enum IndexKind {
38 #[default]
40 BTree,
41 Hash,
43 FullText,
45 Spatial,
47 Other,
49}
50
51#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
53pub enum IndexOrder {
54 #[default]
56 Ascending,
57 Descending,
59 Default,
61}
62
63#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
65pub enum IndexUniqueness {
66 #[default]
68 NonUnique,
69 Unique,
71}
72
73#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
75pub struct IndexColumn {
76 column: ColumnName,
77 order: IndexOrder,
78}
79
80impl IndexColumn {
81 #[must_use]
83 pub const fn new(column: ColumnName, order: IndexOrder) -> Self {
84 Self { column, order }
85 }
86
87 #[must_use]
89 pub const fn column(&self) -> &ColumnName {
90 &self.column
91 }
92
93 #[must_use]
95 pub const fn order(&self) -> IndexOrder {
96 self.order
97 }
98}
99
100#[derive(Clone, Debug, Eq, PartialEq)]
102pub struct IndexMetadata {
103 reference: IndexRef,
104 kind: IndexKind,
105 columns: Vec<IndexColumn>,
106 uniqueness: IndexUniqueness,
107}
108
109impl IndexMetadata {
110 #[must_use]
112 pub const fn new(reference: IndexRef) -> Self {
113 Self {
114 reference,
115 kind: IndexKind::BTree,
116 columns: Vec::new(),
117 uniqueness: IndexUniqueness::NonUnique,
118 }
119 }
120
121 #[must_use]
123 pub const fn with_kind(mut self, kind: IndexKind) -> Self {
124 self.kind = kind;
125 self
126 }
127
128 #[must_use]
130 pub fn with_columns(mut self, columns: Vec<IndexColumn>) -> Self {
131 self.columns = columns;
132 self
133 }
134
135 #[must_use]
137 pub const fn with_uniqueness(mut self, uniqueness: IndexUniqueness) -> Self {
138 self.uniqueness = uniqueness;
139 self
140 }
141
142 #[must_use]
144 pub const fn reference(&self) -> &IndexRef {
145 &self.reference
146 }
147
148 #[must_use]
150 pub fn columns(&self) -> &[IndexColumn] {
151 &self.columns
152 }
153
154 #[must_use]
156 pub const fn uniqueness(&self) -> IndexUniqueness {
157 self.uniqueness
158 }
159}
160
161#[cfg(test)]
162mod tests {
163 use super::{IndexColumn, IndexMetadata, IndexOrder, IndexRef, IndexUniqueness};
164 use use_db_name::{ColumnName, IndexName, TableName};
165
166 #[test]
167 fn stores_index_metadata() -> Result<(), Box<dyn std::error::Error>> {
168 let reference = IndexRef::new(
169 Some(IndexName::new("users_id_idx")?),
170 Some(TableName::new("users")?),
171 );
172 let column = IndexColumn::new(ColumnName::new("id")?, IndexOrder::Ascending);
173 let metadata = IndexMetadata::new(reference)
174 .with_columns(vec![column])
175 .with_uniqueness(IndexUniqueness::Unique);
176
177 assert_eq!(
178 metadata.reference().name().expect("name").as_str(),
179 "users_id_idx"
180 );
181 assert_eq!(metadata.columns()[0].order(), IndexOrder::Ascending);
182 assert_eq!(metadata.uniqueness(), IndexUniqueness::Unique);
183 Ok(())
184 }
185}