database_reflection/reflection/
database.rs1use crate::metadata::consts::{METADATA_CHARSET, METADATA_COLLATION};
2use crate::metadata::WithMetadata;
3use crate::reflection::column::Column;
4use crate::reflection::constraint::{Constraint, ConstraintSide};
5use crate::reflection::table::Table;
6use indexmap::IndexMap;
7use serde::{Deserialize, Serialize};
8use std::collections::HashMap;
9use std::sync::Arc;
10
11#[derive(Clone, Default, Debug, Serialize, Deserialize)]
12pub struct Database {
13 name: String,
14 tables: IndexMap<Arc<String>, Arc<Table>>,
15 constraints: HashMap<Arc<String>, Arc<Constraint>>,
16 metadata: HashMap<String, String>,
17}
18
19impl WithMetadata for Database {
20 fn get_metadata(&self) -> &HashMap<String, String> {
22 &self.metadata
23 }
24
25 fn get_metadata_mut(&mut self) -> &mut HashMap<String, String> {
27 &mut self.metadata
28 }
29}
30
31impl Database {
32 pub fn new(name: impl ToString) -> Database {
34 Database {
35 name: name.to_string(),
36 ..Default::default()
37 }
38 }
39
40 pub fn name(&self) -> &str {
42 &self.name
43 }
44
45 pub fn set_table(&mut self, mut table: Table) -> &mut Database {
47 if table.meta(METADATA_CHARSET).is_none()
48 && table.meta(METADATA_COLLATION).is_none()
49 && self.meta(METADATA_CHARSET).is_some()
50 && self.meta(METADATA_COLLATION).is_some()
51 {
52 table
53 .set_meta(
54 METADATA_CHARSET,
55 self.meta(METADATA_CHARSET).unwrap_or_default(),
56 )
57 .set_meta(
58 METADATA_COLLATION,
59 self.meta(METADATA_COLLATION).unwrap_or_default(),
60 );
61 }
62
63 self.tables.insert(table.name(), Arc::new(table));
64
65 self
66 }
67
68 pub fn table(&self, key: &str) -> Option<Arc<Table>> {
70 self.tables.get(&key.to_string()).cloned()
71 }
72
73 pub fn tables(&self) -> indexmap::map::Iter<'_, Arc<String>, Arc<Table>> {
75 self.tables.iter()
76 }
77
78 pub fn set_constraint(&mut self, constraint: Constraint) -> &mut Database {
80 self.constraints
81 .insert(constraint.name(), Arc::new(constraint));
82
83 self
84 }
85
86 pub fn constraint(&self, key: &str) -> Option<Arc<Constraint>> {
88 #[allow(clippy::unnecessary_to_owned)]
89 self.constraints.get(&key.to_string()).cloned()
90 }
91
92 pub fn constraints(
94 &self,
95 ) -> std::collections::hash_map::Iter<'_, Arc<String>, Arc<Constraint>> {
96 self.constraints.iter()
97 }
98
99 pub fn constraints_by_table(
101 &self,
102 table: Arc<Table>,
103 side: Option<ConstraintSide>,
104 ) -> Vec<Arc<Constraint>> {
105 self.constraints
106 .values()
107 .filter(|c| {
108 if c.local().table() == table.name() && (side != Some(ConstraintSide::Foreign)) {
109 return true;
110 }
111
112 if c.foreign().table() == table.name() && (side != Some(ConstraintSide::Local)) {
113 return true;
114 }
115
116 false
117 })
118 .cloned()
119 .collect::<Vec<Arc<Constraint>>>()
120 }
121
122 pub fn constraints_by_column(
124 &self,
125 column: Arc<Column>,
126 side: Option<ConstraintSide>,
127 ) -> Vec<Arc<Constraint>> {
128 self.constraints
129 .values()
130 .filter(|c| {
131 if c.local() == column.as_ref() && (side != Some(ConstraintSide::Foreign)) {
132 return true;
133 }
134
135 if c.foreign() == column.as_ref() && (side != Some(ConstraintSide::Local)) {
136 return true;
137 }
138
139 false
140 })
141 .cloned()
142 .collect::<Vec<Arc<Constraint>>>()
143 }
144
145 pub fn constraints_by_column_name(
147 &self,
148 column_name: Arc<String>,
149 side: Option<ConstraintSide>,
150 ) -> Vec<Arc<Constraint>> {
151 self.constraints
152 .values()
153 .filter(|c| {
154 if c.local().name() == column_name && (side != Some(ConstraintSide::Foreign)) {
155 return true;
156 }
157
158 if c.foreign().name() == column_name && (side != Some(ConstraintSide::Local)) {
159 return true;
160 }
161
162 false
163 })
164 .cloned()
165 .collect::<Vec<Arc<Constraint>>>()
166 }
167}