use crate::metadata::consts::{METADATA_CHARSET, METADATA_COLLATION};
use crate::metadata::WithMetadata;
use crate::reflection::column::Column;
use crate::reflection::constraint::{Constraint, ConstraintSide};
use crate::reflection::table::Table;
use indexmap::IndexMap;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::sync::Arc;
#[derive(Clone, Default, Debug, Serialize, Deserialize)]
pub struct Database {
name: String,
tables: IndexMap<Arc<String>, Arc<Table>>,
constraints: HashMap<Arc<String>, Arc<Constraint>>,
metadata: HashMap<String, String>,
}
impl WithMetadata for Database {
fn get_metadata(&self) -> &HashMap<String, String> {
&self.metadata
}
fn get_metadata_mut(&mut self) -> &mut HashMap<String, String> {
&mut self.metadata
}
}
impl Database {
pub fn new(name: impl ToString) -> Database {
Database {
name: name.to_string(),
..Default::default()
}
}
pub fn name(&self) -> &str {
&self.name
}
pub fn set_table(&mut self, mut table: Table) -> &mut Database {
if table.meta(METADATA_CHARSET) == None
&& table.meta(METADATA_COLLATION) == None
&& self.meta(METADATA_CHARSET).is_some()
&& self.meta(METADATA_COLLATION).is_some()
{
table
.set_meta(
METADATA_CHARSET,
self.meta(METADATA_CHARSET).unwrap_or_default(),
)
.set_meta(
METADATA_COLLATION,
self.meta(METADATA_COLLATION).unwrap_or_default(),
);
}
self.tables.insert(table.name(), Arc::new(table));
self
}
pub fn table(&self, key: &str) -> Option<Arc<Table>> {
self.tables.get(&key.to_string()).cloned()
}
pub fn tables(&self) -> indexmap::map::Iter<'_, Arc<String>, Arc<Table>> {
self.tables.iter()
}
pub fn set_constraint(&mut self, constraint: Constraint) -> &mut Database {
self.constraints
.insert(constraint.name(), Arc::new(constraint));
self
}
pub fn constraint(&self, key: &str) -> Option<Arc<Constraint>> {
self.constraints.get(&key.to_string()).cloned()
}
pub fn constraints(
&self,
) -> std::collections::hash_map::Iter<'_, Arc<String>, Arc<Constraint>> {
self.constraints.iter()
}
pub fn constraints_by_table(
&self,
table: Arc<Table>,
side: Option<ConstraintSide>,
) -> Vec<Arc<Constraint>> {
self.constraints
.values()
.filter(|c| {
if c.local().table() == table.name() && (side != Some(ConstraintSide::Foreign)) {
return true;
}
if c.foreign().table() == table.name() && (side != Some(ConstraintSide::Local)) {
return true;
}
false
})
.cloned()
.collect::<Vec<Arc<Constraint>>>()
}
pub fn constraints_by_column(
&self,
column: Arc<Column>,
side: Option<ConstraintSide>,
) -> Vec<Arc<Constraint>> {
self.constraints
.values()
.filter(|c| {
if c.local() == column.as_ref() && (side != Some(ConstraintSide::Foreign)) {
return true;
}
if c.foreign() == column.as_ref() && (side != Some(ConstraintSide::Local)) {
return true;
}
false
})
.cloned()
.collect::<Vec<Arc<Constraint>>>()
}
pub fn constraints_by_column_name(
&self,
column_name: Arc<String>,
side: Option<ConstraintSide>,
) -> Vec<Arc<Constraint>> {
self.constraints
.values()
.filter(|c| {
if c.local().name() == column_name && (side != Some(ConstraintSide::Foreign)) {
return true;
}
if c.foreign().name() == column_name && (side != Some(ConstraintSide::Local)) {
return true;
}
false
})
.cloned()
.collect::<Vec<Arc<Constraint>>>()
}
}