use crate::prelude::*;
use crate::{SQL, SQLColumnInfo, SQLParam, SQLSchema, SQLSchemaType, ToSQL};
use core::any::Any;
pub trait SQLModel<'a, V: SQLParam>: ToSQL<'a, V> {
fn columns(&self) -> Cow<'static, [&'static dyn SQLColumnInfo]>;
fn values(&self) -> SQL<'a, V>;
}
pub trait SQLPartial<'a, Value: SQLParam> {
type Partial: SQLModel<'a, Value> + Default + 'a;
fn partial() -> Self::Partial {
Default::default()
}
}
pub trait SQLTable<'a, Type: SQLSchemaType, Value: SQLParam + 'a>:
SQLSchema<'a, Type, Value> + SQLTableInfo + Default + Clone
{
type Select: SQLModel<'a, Value> + SQLPartial<'a, Value> + Default + 'a;
type Insert<T>: SQLModel<'a, Value> + Default;
type Update: SQLModel<'a, Value> + Default + 'a;
type Aliased: SQLTable<'a, Type, Value>;
fn alias(name: &'static str) -> Self::Aliased;
}
pub trait SQLTableInfo: Any + Send + Sync {
fn name(&self) -> &str;
fn schema(&self) -> Option<&str> {
None
}
fn qualified_name(&self) -> Cow<'static, str> {
match self.schema() {
Some(schema) => Cow::Owned(format!("{schema}.{}", self.name())),
None => Cow::Owned(self.name().to_string()),
}
}
fn columns(&self) -> &'static [&'static dyn SQLColumnInfo];
fn dependencies(&self) -> &'static [&'static dyn SQLTableInfo];
fn column_named(&self, name: &str) -> Option<&'static dyn SQLColumnInfo> {
self.columns()
.iter()
.copied()
.find(|col| col.name() == name)
}
}
impl<T: SQLTableInfo> SQLTableInfo for &'static T {
fn name(&self) -> &str {
(*self).name()
}
fn schema(&self) -> Option<&str> {
(*self).schema()
}
fn qualified_name(&self) -> Cow<'static, str> {
(*self).qualified_name()
}
fn columns(&self) -> &'static [&'static dyn SQLColumnInfo] {
(*self).columns()
}
fn dependencies(&self) -> &'static [&'static dyn SQLTableInfo] {
(*self).dependencies()
}
}
impl core::fmt::Debug for dyn SQLTableInfo {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("SQLTableInfo")
.field("name", &self.name())
.field("schema", &self.schema())
.field("qualified_name", &self.qualified_name())
.field("columns", &self.columns())
.finish()
}
}
pub trait AsTableInfo: Sized + SQLTableInfo {
fn as_table(&self) -> &dyn SQLTableInfo {
self
}
}