use crate::{
db::{StatementContext, StatementRow},
schema::entity::{Entity, EntityVisitor},
schema::relation::{Relation, RelationData, RelationDomain, RelationMap, RelationRange},
DBResult,
};
mod datum_common;
mod datum_list;
pub trait Datum: Clone + std::fmt::Debug {
const INTERNAL_DATUM: bool = true;
fn sql_type() -> &'static str;
fn debug_field(&self, field: &'static str, fmt: &mut std::fmt::DebugStruct)
where
Self: Sized,
{
fmt.field(field, self);
}
fn bind_to(&self, _stmt: &mut StatementContext, index: i32) -> DBResult<()>;
fn build_from(
_adata: RelationData,
_stmt: &mut StatementRow,
_index: &mut i32,
) -> DBResult<Self>
where
Self: Sized,
{
unreachable!()
}
#[doc(hidden)]
fn update_adata(&mut self, _adata: RelationData) {}
fn accept_entity_visitor(_: &mut impl EntityVisitor) {}
fn accept_discriminator(d: &mut impl DatumDiscriminator)
where
Self: Sized,
{
d.visit_bare_field::<Self>();
}
fn accept_discriminator_ref(&self, d: &mut impl DatumDiscriminatorRef)
where
Self: Sized,
{
d.visit_bare_field::<Self>(self);
}
}
pub trait OwnedDatum: 'static + Datum {
type RefData<'a>: Datum + BorrowedDatum<'a, Self>;
fn as_ref(&self) -> Self::RefData<'_>;
}
pub trait BorrowedDatum<'a, Own: OwnedDatum>: Copy + Datum {
fn as_owned(&self) -> Own;
}
pub trait DatumDiscriminator {
fn visit_entity_id<E: Entity>(&mut self);
fn visit_serialized<T: serde::Serialize + serde::de::DeserializeOwned>(&mut self);
fn visit_bare_field<T: Datum>(&mut self);
fn visit_relation_map<E: Entity>(&mut self);
fn visit_relation_domain<R: Relation>(&mut self);
fn visit_relation_range<R: Relation>(&mut self);
fn visit_value<T: serde::de::DeserializeOwned>(&mut self);
}
pub trait DatumDiscriminatorRef {
fn visit_entity_id<E: Entity>(&mut self, _: &E::ID);
fn visit_serialized<T: serde::Serialize + serde::de::DeserializeOwned>(&mut self, _: &T);
fn visit_bare_field<T: Datum>(&mut self, _: &T);
fn visit_relation_map<E: Entity>(&mut self, _: &RelationMap<E>);
fn visit_relation_domain<R: Relation>(&mut self, _: &RelationDomain<R>);
fn visit_relation_range<R: Relation>(&mut self, _: &RelationRange<R>);
fn visit_value<T: serde::de::DeserializeOwned>(&mut self, _: &T);
}
pub trait OwnedDatumList: Clone {
const IS_EMPTY: bool = false;
type ListHead: OwnedDatum;
type ListTail: OwnedDatumList;
type RefList<'l>: BorrowedDatumList<'l, Self>
where
Self: 'l;
fn list_head(&self) -> &Self::ListHead;
fn list_tail(&self) -> Self::ListTail;
fn accept(&self, visitor: &mut impl DatumVisitor) -> DBResult<()>;
fn build_equivalent<'l>(
strs: impl Iterator<Item = &'l str>,
) -> impl BorrowedDatumList<'l, Self>;
}
pub trait BorrowedDatumList<'l, O: OwnedDatumList>: Copy {
const IS_EMPTY: bool = false;
type ListHead: BorrowedDatum<'l, O::ListHead>;
type ListTail: BorrowedDatumList<'l, O::ListTail>;
fn list_head(&self) -> &Self::ListHead;
fn list_tail(&self) -> Self::ListTail;
fn accept(&self, visitor: &mut impl DatumVisitor) -> DBResult<()>;
}
pub trait DatumVisitor {
fn visit<ED: Datum>(&mut self, datum: &ED) -> DBResult<()>;
}
#[derive(Debug, Clone, Copy)]
pub struct StringQuery<'l>(pub &'l str);
impl<'l> Datum for StringQuery<'l> {
fn sql_type() -> &'static str {
"N/A"
}
fn bind_to(&self, stmt: &mut StatementContext, index: i32) -> DBResult<()> {
stmt.bind(index, self.0)
}
fn build_from(_: RelationData, _: &mut StatementRow, _: &mut i32) -> DBResult<Self> {
unreachable!()
}
}
impl<'l, O: OwnedDatum> BorrowedDatum<'l, O> for StringQuery<'l> {
fn as_owned(&self) -> O {
unreachable!()
}
}