Skip to main content

use_db_index/
lib.rs

1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4//! Index metadata primitives for `RustUse`.
5
6use use_db_name::{ColumnName, IndexName, TableName};
7
8/// Index reference metadata.
9#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
10pub struct IndexRef {
11    name: Option<IndexName>,
12    table: Option<TableName>,
13}
14
15impl IndexRef {
16    /// Creates index reference metadata.
17    #[must_use]
18    pub const fn new(name: Option<IndexName>, table: Option<TableName>) -> Self {
19        Self { name, table }
20    }
21
22    /// Returns the optional index name.
23    #[must_use]
24    pub const fn name(&self) -> Option<&IndexName> {
25        self.name.as_ref()
26    }
27
28    /// Returns the optional table name.
29    #[must_use]
30    pub const fn table(&self) -> Option<&TableName> {
31        self.table.as_ref()
32    }
33}
34
35/// Broad index kind.
36#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
37pub enum IndexKind {
38    /// B-tree-like index.
39    #[default]
40    BTree,
41    /// Hash-like index.
42    Hash,
43    /// Full-text or search index.
44    FullText,
45    /// Spatial index.
46    Spatial,
47    /// Other or unspecified index kind.
48    Other,
49}
50
51/// Index column sort order.
52#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
53pub enum IndexOrder {
54    /// Ascending order.
55    #[default]
56    Ascending,
57    /// Descending order.
58    Descending,
59    /// Engine default order.
60    Default,
61}
62
63/// Index uniqueness metadata.
64#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
65pub enum IndexUniqueness {
66    /// Non-unique index.
67    #[default]
68    NonUnique,
69    /// Unique index.
70    Unique,
71}
72
73/// An indexed column.
74#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
75pub struct IndexColumn {
76    column: ColumnName,
77    order: IndexOrder,
78}
79
80impl IndexColumn {
81    /// Creates indexed column metadata.
82    #[must_use]
83    pub const fn new(column: ColumnName, order: IndexOrder) -> Self {
84        Self { column, order }
85    }
86
87    /// Returns the column name.
88    #[must_use]
89    pub const fn column(&self) -> &ColumnName {
90        &self.column
91    }
92
93    /// Returns the order metadata.
94    #[must_use]
95    pub const fn order(&self) -> IndexOrder {
96        self.order
97    }
98}
99
100/// Index metadata.
101#[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    /// Creates index metadata.
111    #[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    /// Sets the index kind.
122    #[must_use]
123    pub const fn with_kind(mut self, kind: IndexKind) -> Self {
124        self.kind = kind;
125        self
126    }
127
128    /// Sets indexed columns.
129    #[must_use]
130    pub fn with_columns(mut self, columns: Vec<IndexColumn>) -> Self {
131        self.columns = columns;
132        self
133    }
134
135    /// Sets uniqueness metadata.
136    #[must_use]
137    pub const fn with_uniqueness(mut self, uniqueness: IndexUniqueness) -> Self {
138        self.uniqueness = uniqueness;
139        self
140    }
141
142    /// Returns the index reference.
143    #[must_use]
144    pub const fn reference(&self) -> &IndexRef {
145        &self.reference
146    }
147
148    /// Returns indexed columns.
149    #[must_use]
150    pub fn columns(&self) -> &[IndexColumn] {
151        &self.columns
152    }
153
154    /// Returns uniqueness metadata.
155    #[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}