|
@@ -1,311 +0,0 @@
|
|
|
-use std::{
|
|
|
- collections::{HashMap, HashSet},
|
|
|
- hash::Hash,
|
|
|
- marker::PhantomData,
|
|
|
- sync::Mutex,
|
|
|
-};
|
|
|
-
|
|
|
-use crate::{
|
|
|
- db::{StatementContext, StatementRow},
|
|
|
- schema::{
|
|
|
- datum::{ConcreteDatum, Datum, DatumList},
|
|
|
- entity::{Entity, EntityID, EntityPart, EntityPartList, EntityPartVisitor},
|
|
|
- relation::RelationData,
|
|
|
- DatabaseItemVisitor, Schema,
|
|
|
- },
|
|
|
- DBResult,
|
|
|
-};
|
|
|
-
|
|
|
-// ----------------------------------------------------------------------
|
|
|
-// Entity-related New<> adapter
|
|
|
-// ----------------------------------------------------------------------
|
|
|
-
|
|
|
-pub struct NewID<OE: Entity> {
|
|
|
- value: OE::ID,
|
|
|
-}
|
|
|
-
|
|
|
-impl<OE: Entity> std::fmt::Debug for NewID<OE> {
|
|
|
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
- f.write_fmt(format_args!("NewID({})", self.value.into_raw()))
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-impl<OE: Entity> Clone for NewID<OE> {
|
|
|
- fn clone(&self) -> Self {
|
|
|
- Self {
|
|
|
- value: self.value.clone(),
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-impl<OE: Entity> Copy for NewID<OE> {}
|
|
|
-
|
|
|
-impl<OE: Entity> Hash for NewID<OE> {
|
|
|
- fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
|
|
- self.value.hash(state)
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-impl<OE: Entity> PartialEq for NewID<OE> {
|
|
|
- fn eq(&self, other: &Self) -> bool {
|
|
|
- self.value.eq(&other.value)
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-impl<OE: Entity> PartialOrd for NewID<OE> {
|
|
|
- fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
|
|
- self.value.partial_cmp(&other.value)
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-impl<OE: Entity> EntityID for NewID<OE> {
|
|
|
- type Entity = New<OE>;
|
|
|
-
|
|
|
- fn from_raw(id: i64) -> Self {
|
|
|
- Self {
|
|
|
- value: OE::ID::from_raw(id),
|
|
|
- }
|
|
|
- }
|
|
|
- fn into_raw(self) -> i64 {
|
|
|
- self.value.into_raw()
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-impl<OE: Entity> Datum for NewID<OE> {
|
|
|
- fn sql_type() -> &'static str {
|
|
|
- OE::ID::sql_type()
|
|
|
- }
|
|
|
- fn bind_to(&self, stmt: &mut StatementContext, index: i32) {
|
|
|
- self.value.bind_to(stmt, index)
|
|
|
- }
|
|
|
- fn build_from(adata: RelationData, stmt: &mut StatementRow, index: &mut i32) -> DBResult<Self>
|
|
|
- where
|
|
|
- Self: Sized,
|
|
|
- {
|
|
|
- OE::ID::build_from(adata, stmt, index).map(|value| Self { value })
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-impl<OE: Entity> ConcreteDatum for NewID<OE> {}
|
|
|
-
|
|
|
-pub struct NewIDPart<OE: Entity> {
|
|
|
- _ghost: std::marker::PhantomData<&'static OE>,
|
|
|
-}
|
|
|
-
|
|
|
-impl<OE: Entity> Default for NewIDPart<OE> {
|
|
|
- fn default() -> Self {
|
|
|
- Self {
|
|
|
- _ghost: std::marker::PhantomData,
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-impl<OE: Entity> Clone for NewIDPart<OE> {
|
|
|
- fn clone(&self) -> Self {
|
|
|
- Self::default()
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-impl<OE: Entity> EntityPart for NewIDPart<OE> {
|
|
|
- type Entity = New<OE>;
|
|
|
- type Datum = NewID<OE>;
|
|
|
-
|
|
|
- fn desc() -> Option<&'static str> {
|
|
|
- None
|
|
|
- }
|
|
|
- fn unique() -> bool {
|
|
|
- false
|
|
|
- }
|
|
|
- fn part_name() -> &'static str {
|
|
|
- "id"
|
|
|
- }
|
|
|
- fn get_datum(_from: &Self::Entity) -> &Self::Datum {
|
|
|
- unreachable!()
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-pub struct NewPart<OE: Entity, OP: EntityPart<Entity = OE>> {
|
|
|
- _ghost: std::marker::PhantomData<&'static (OE, OP)>,
|
|
|
-}
|
|
|
-
|
|
|
-impl<OE: Entity, OP: EntityPart<Entity = OE>> Default for NewPart<OE, OP> {
|
|
|
- fn default() -> Self {
|
|
|
- Self {
|
|
|
- _ghost: std::marker::PhantomData,
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-impl<OE: Entity, OP: EntityPart<Entity = OE>> Clone for NewPart<OE, OP> {
|
|
|
- fn clone(&self) -> Self {
|
|
|
- Self::default()
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-impl<OE: Entity, OP: EntityPart<Entity = OE>> EntityPart for NewPart<OE, OP> {
|
|
|
- type Entity = New<OE>;
|
|
|
- type Datum = OP::Datum;
|
|
|
-
|
|
|
- fn desc() -> Option<&'static str> {
|
|
|
- OP::desc()
|
|
|
- }
|
|
|
- fn unique() -> bool {
|
|
|
- OP::unique()
|
|
|
- }
|
|
|
- fn part_name() -> &'static str {
|
|
|
- OP::part_name()
|
|
|
- }
|
|
|
- fn get_datum(from: &Self::Entity) -> &Self::Datum {
|
|
|
- OP::get_datum(&from.value)
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-pub struct NewPartList<OE: Entity, OPL: EntityPartList> {
|
|
|
- _ghost: std::marker::PhantomData<&'static (OE, OPL)>,
|
|
|
-}
|
|
|
-
|
|
|
-impl<OE: Entity, OPL: EntityPartList<Entity = OE>> EntityPartList for NewPartList<OE, OPL> {
|
|
|
- type Entity = New<OE>;
|
|
|
- type ListHead = NewPart<OE, OPL::ListHead>;
|
|
|
- type ListTail = NewPartList<OE, OPL::ListTail>;
|
|
|
- type DatumList = OPL::DatumList;
|
|
|
-
|
|
|
- const IS_EMPTY: bool = OPL::IS_EMPTY;
|
|
|
-
|
|
|
- fn build_datum_list(stmt: &mut StatementRow) -> DBResult<Self::DatumList> {
|
|
|
- OPL::build_datum_list(stmt)
|
|
|
- }
|
|
|
- fn accept_part_visitor(visitor: &mut impl EntityPartVisitor<Entity = Self::Entity>) {
|
|
|
- if Self::IS_EMPTY {
|
|
|
- return;
|
|
|
- }
|
|
|
- Self::ListHead::accept_part_visitor(visitor);
|
|
|
- Self::ListTail::accept_part_visitor(visitor);
|
|
|
- }
|
|
|
- fn accept_part_visitor_ref(
|
|
|
- datum_list: &Self::DatumList,
|
|
|
- visitor: &mut impl EntityPartVisitor<Entity = Self::Entity>,
|
|
|
- ) {
|
|
|
- if Self::IS_EMPTY {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- visitor.visit_datum::<Self::ListHead>(datum_list.list_head());
|
|
|
-
|
|
|
- let tail = datum_list.list_tail();
|
|
|
- Self::ListTail::accept_part_visitor_ref(&tail, visitor);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-#[derive(Debug)]
|
|
|
-pub struct New<E: Entity> {
|
|
|
- value: E,
|
|
|
-}
|
|
|
-
|
|
|
-lazy_static::lazy_static! {
|
|
|
- static ref NEWNAMES : Mutex<HashMap<std::any::TypeId, &'static str>> = {
|
|
|
- Default::default()
|
|
|
- };
|
|
|
-}
|
|
|
-
|
|
|
-impl<E: Entity> Entity for New<E> {
|
|
|
- type ID = NewID<E>;
|
|
|
- type Keys = NewPartList<E, E::Keys>;
|
|
|
- type Parts = NewPartList<E, E::Parts>;
|
|
|
- type IDPart = NewIDPart<E>;
|
|
|
-
|
|
|
- fn entity_name() -> &'static str {
|
|
|
- let mut nn = NEWNAMES.lock().unwrap();
|
|
|
- let e = nn.entry(std::any::TypeId::of::<Self>());
|
|
|
- e.or_insert_with(|| Box::leak(format!("NEW_{}", E::entity_name()).into_boxed_str()))
|
|
|
- }
|
|
|
-
|
|
|
- fn build(values: <Self::Parts as EntityPartList>::DatumList) -> Self {
|
|
|
- Self {
|
|
|
- value: E::build(values),
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- fn accept_part_visitor(visitor: &mut impl EntityPartVisitor<Entity = Self>) {
|
|
|
- Self::Parts::accept_part_visitor(visitor)
|
|
|
- }
|
|
|
-
|
|
|
- fn accept_part_visitor_ref(&self, visitor: &mut impl EntityPartVisitor<Entity = Self>) {
|
|
|
- struct PassthroughVisitor<'l, E: Entity, EPV: EntityPartVisitor<Entity = New<E>>>(
|
|
|
- &'l mut EPV,
|
|
|
- );
|
|
|
- impl<'l, E: Entity, EPV: EntityPartVisitor<Entity = New<E>>> EntityPartVisitor
|
|
|
- for PassthroughVisitor<'l, E, EPV>
|
|
|
- {
|
|
|
- type Entity = E;
|
|
|
- fn visit_datum<EP: EntityPart<Entity = Self::Entity>>(&mut self, datum: &EP::Datum) {
|
|
|
- self.0.visit_datum::<NewPart<E, EP>>(datum);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- let mut pv = PassthroughVisitor(visitor);
|
|
|
- self.value.accept_part_visitor_ref(&mut pv);
|
|
|
- }
|
|
|
-
|
|
|
- fn accept_part_visitor_mut(&mut self, visitor: &mut impl EntityPartVisitor<Entity = Self>) {
|
|
|
- struct PassthroughVisitor<'l, E: Entity, EPV: EntityPartVisitor<Entity = New<E>>>(
|
|
|
- &'l mut EPV,
|
|
|
- );
|
|
|
- impl<'l, E: Entity, EPV: EntityPartVisitor<Entity = New<E>>> EntityPartVisitor
|
|
|
- for PassthroughVisitor<'l, E, EPV>
|
|
|
- {
|
|
|
- type Entity = E;
|
|
|
- fn visit_datum_mut<EP: EntityPart<Entity = Self::Entity>>(
|
|
|
- &mut self,
|
|
|
- datum: &mut EP::Datum,
|
|
|
- ) {
|
|
|
- self.0.visit_datum_mut::<NewPart<E, EP>>(datum);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- let mut pv = PassthroughVisitor(visitor);
|
|
|
- self.value.accept_part_visitor_mut(&mut pv);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// ----------------------------------------------------------------------
|
|
|
-// Schema-level adaptation
|
|
|
-// ----------------------------------------------------------------------
|
|
|
-pub struct WrapSchema<S: Schema> {
|
|
|
- base: S,
|
|
|
- towrap: HashSet<String>,
|
|
|
-}
|
|
|
-
|
|
|
-impl<S: Schema> WrapSchema<S> {
|
|
|
- pub fn new(base: S, towrap: HashSet<String>) -> Self {
|
|
|
- Self { base, towrap }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-impl<S: Schema> Schema for WrapSchema<S> {
|
|
|
- fn accept_item_visitor(&self, visitor: &mut impl DatabaseItemVisitor)
|
|
|
- where
|
|
|
- Self: Sized,
|
|
|
- {
|
|
|
- struct InterceptingVisitor<'a, S: Schema, V: DatabaseItemVisitor>(
|
|
|
- &'a WrapSchema<S>,
|
|
|
- &'a mut V,
|
|
|
- );
|
|
|
- impl<'a, S: Schema, V: DatabaseItemVisitor> DatabaseItemVisitor for InterceptingVisitor<'a, S, V> {
|
|
|
- fn visit_idmap<T: Entity>(&mut self)
|
|
|
- where
|
|
|
- Self: Sized,
|
|
|
- {
|
|
|
- }
|
|
|
-
|
|
|
- fn visit_index<T: Entity, PL: EntityPartList<Entity = T>>(&mut self)
|
|
|
- where
|
|
|
- Self: Sized,
|
|
|
- {
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- let mut iv = InterceptingVisitor(self, visitor);
|
|
|
- self.base.accept_item_visitor(&mut iv);
|
|
|
- }
|
|
|
-}
|