use indexmap::IndexMap;
use crate::dict::Compound;
use crate::span::Span;
#[cfg(feature = "serde")]
use serde::Serialize;
#[cfg_attr(
feature = "serde",
derive(Serialize),
serde(tag = "kind", rename_all = "camelCase")
)]
#[derive(Debug, Clone)]
pub enum Origin {
Own,
Mixin {
name: String,
#[cfg_attr(feature = "serde", serde(skip))]
def_span: Span,
},
Blueprint {
name: String,
#[cfg_attr(feature = "serde", serde(skip))]
def_span: Span,
#[cfg_attr(feature = "serde", serde(skip))]
apply_span: Span,
},
Generated { by: String },
}
#[cfg_attr(feature = "serde", derive(Serialize), serde(rename_all = "camelCase"))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Val {
Literal(String),
Eval(String),
}
#[cfg_attr(feature = "serde", derive(Serialize), serde(rename_all = "camelCase"))]
#[derive(Debug, Clone)]
pub struct Column {
pub name: String,
#[cfg_attr(feature = "serde", serde(rename = "type"))]
pub ty: String,
pub null: bool,
pub default: Option<Val>,
pub on_update: Option<Val>,
pub comment: Option<String>,
pub origin: Origin,
#[cfg_attr(feature = "serde", serde(skip))]
pub span: Span,
}
#[cfg_attr(feature = "serde", derive(Serialize), serde(rename_all = "camelCase"))]
#[derive(Debug, Clone)]
pub struct Index {
pub name: String,
pub columns: Vec<String>,
pub unique: bool,
#[cfg_attr(feature = "serde", serde(skip))]
pub span: Span,
}
#[cfg_attr(feature = "serde", derive(Serialize), serde(rename_all = "camelCase"))]
#[derive(Debug, Clone)]
pub struct ForeignKey {
pub alias: String,
pub columns: Vec<String>,
pub ref_table: String,
pub ref_columns: Vec<String>,
pub on_delete: String,
pub on_update: String,
#[cfg_attr(feature = "serde", serde(skip))]
pub span: Span,
}
#[cfg_attr(feature = "serde", derive(Serialize), serde(rename_all = "camelCase"))]
#[derive(Debug, Clone)]
pub struct Reverse {
pub alias: String,
pub from_table: String,
pub via: Vec<String>,
pub unique: bool,
#[cfg_attr(feature = "serde", serde(skip))]
pub span: Span,
}
#[cfg_attr(feature = "serde", derive(Serialize), serde(rename_all = "camelCase"))]
#[derive(Debug, Clone)]
pub struct Table {
pub name: String,
#[cfg_attr(feature = "serde", serde(skip))]
pub noun: Option<Compound>,
pub singular: Option<String>,
pub plural: Option<String>,
pub comment: Option<String>,
pub columns: IndexMap<String, Column>,
pub pk: Vec<String>,
pub indexes: Vec<Index>,
pub foreign_keys: Vec<ForeignKey>,
pub reverses: Vec<Reverse>,
pub origin: Origin,
#[cfg_attr(feature = "serde", serde(skip))]
pub span: Span,
}
#[cfg_attr(feature = "serde", derive(Serialize), serde(rename_all = "camelCase"))]
#[derive(Debug, Clone, Default)]
pub struct Schema {
pub tables: Vec<Table>,
}
impl Schema {
pub fn table(&self, name: &str) -> Option<&Table> {
self.tables.iter().find(|t| t.name == name)
}
pub fn table_by_noun(&self, name: &str) -> Option<&Table> {
self.tables
.iter()
.find(|t| t.noun.as_ref().and_then(Compound::as_single_noun) == Some(name))
}
}