use crate::metadata::consts::{METADATA_CHARSET, METADATA_COLLATION, METADATA_FLAG_PRIMARY};
use crate::metadata::WithMetadata;
use crate::reflection::column::Column;
use crate::reflection::index::Index;
use indexmap::IndexMap;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::slice::Iter;
use std::sync::Arc;
#[derive(Clone, Default, Debug, Serialize, Deserialize)]
pub struct Table {
name: Arc<String>,
primary_key: Vec<Arc<String>>,
columns: IndexMap<Arc<String>, Arc<Column>>,
indexes: IndexMap<Arc<String>, Index>,
metadata: HashMap<String, String>,
}
impl WithMetadata for Table {
fn get_metadata(&self) -> &HashMap<String, String> {
&self.metadata
}
fn get_metadata_mut(&mut self) -> &mut HashMap<String, String> {
&mut self.metadata
}
}
impl Table {
pub fn new(name: impl ToString) -> Table {
Table {
name: Arc::new(name.to_string()),
..Default::default()
}
}
pub fn name(&self) -> Arc<String> {
self.name.clone()
}
pub fn set_column(&mut self, mut column: Column) -> &mut Table {
if column.datatype().is_text()
&& column.meta(METADATA_CHARSET).is_none()
&& column.meta(METADATA_COLLATION).is_none()
&& self.meta(METADATA_CHARSET).is_some()
&& self.meta(METADATA_COLLATION).is_some()
{
column
.set_meta(
METADATA_CHARSET,
self.meta(METADATA_CHARSET).unwrap_or_default(),
)
.set_meta(
METADATA_COLLATION,
self.meta(METADATA_COLLATION).unwrap_or_default(),
);
}
if column.meta_flag(METADATA_FLAG_PRIMARY) && !self.primary_key.contains(&column.name()) {
self.primary_key.push(column.name());
}
self.columns.insert(column.name(), Arc::new(column));
self
}
pub fn column(&self, key: &str) -> Option<Arc<Column>> {
self.columns.get(&key.to_string()).cloned()
}
pub fn columns(&self) -> indexmap::map::Iter<'_, Arc<String>, Arc<Column>> {
self.columns.iter()
}
pub fn set_index(&mut self, index: Index) -> &mut Table {
if index.primary() && !self.primary_key.contains(&index.column().name()) {
self.primary_key.push(index.column().name());
}
self.indexes.insert(index.name(), index);
self
}
pub fn index(&self, key: &str) -> Option<&Index> {
self.indexes.get(&key.to_string())
}
pub fn index_by_column_name(&self, column_name: Arc<String>) -> Option<Index> {
self.indexes
.iter()
.find(|(_, c)| c.column().name() == column_name)
.map(|(_, c)| c.clone())
}
pub fn index_by_column(&self, column: &Column) -> Option<Index> {
self.indexes
.iter()
.find(|(_, c)| c.column() == column)
.map(|(_, c)| c.clone())
}
pub fn indexes(&self) -> indexmap::map::Iter<'_, Arc<String>, Index> {
self.indexes.iter()
}
pub fn primary_key_count(&self) -> usize {
self.primary_key.len()
}
pub fn primary_key(&self) -> Option<Arc<String>> {
self.primary_key.first().cloned()
}
pub fn primary_key_column(&self) -> Option<Arc<Column>> {
self.primary_key
.first()
.map(|k| self.columns.get(k).cloned())
.unwrap()
}
pub fn primary_keys(&self) -> Iter<'_, Arc<String>> {
self.primary_key.iter()
}
pub fn primary_key_columns(&self) -> Vec<Arc<Column>> {
self.columns
.iter()
.filter(|kv| self.primary_key.contains(kv.0))
.map(|kv| kv.1.clone())
.collect::<Vec<Arc<Column>>>()
}
}