icydb_schema/node/
index.rs

1use crate::prelude::*;
2use std::{
3    fmt::{self, Display},
4    ops::Not,
5};
6
7///
8/// Index
9///
10
11#[derive(Clone, Debug, Serialize)]
12pub struct Index {
13    pub store: &'static str,
14    pub fields: &'static [&'static str],
15
16    #[serde(default, skip_serializing_if = "Not::not")]
17    pub unique: bool,
18}
19
20impl Index {
21    #[must_use]
22    pub fn is_prefix_of(&self, other: &Self) -> bool {
23        self.fields.len() < other.fields.len() && other.fields.starts_with(self.fields)
24    }
25}
26
27impl Display for Index {
28    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29        let fields = self.fields.join(", ");
30
31        if self.unique {
32            write!(f, "UNIQUE {}({})", self.store, fields)
33        } else {
34            write!(f, "{}({})", self.store, fields)
35        }
36    }
37}
38
39impl MacroNode for Index {
40    fn as_any(&self) -> &dyn std::any::Any {
41        self
42    }
43}
44
45impl ValidateNode for Index {
46    fn validate(&self) -> Result<(), ErrorTree> {
47        let mut errs = ErrorTree::new();
48        let schema = schema_read();
49
50        // store
51        match schema.cast_node::<Store>(self.store) {
52            Ok(store) if !matches!(store.ty, StoreType::Index) => {
53                err!(errs, "store is not type Index");
54            }
55            Ok(_) => {}
56            Err(e) => errs.add(e),
57        }
58
59        errs.result()
60    }
61}
62
63impl VisitableNode for Index {
64    fn route_key(&self) -> String {
65        self.fields.join(", ")
66    }
67}