|
@@ -1,16 +1,26 @@
|
|
-use crate::{Entity, model::Modelable, entity::EntityColumn};
|
|
|
|
|
|
+use crate::{entity::EntityColumn, model::Modelable, Entity};
|
|
|
|
|
|
use std::marker::PhantomData;
|
|
use std::marker::PhantomData;
|
|
|
|
|
|
pub trait BuildingBlock {
|
|
pub trait BuildingBlock {
|
|
- fn build_query(&self) -> String { String::new() }
|
|
|
|
|
|
+ fn build_query(&self) -> String {
|
|
|
|
+ String::new()
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
-pub struct Builder { }
|
|
|
|
|
|
+pub struct Builder {}
|
|
|
|
|
|
impl Builder {
|
|
impl Builder {
|
|
- pub fn get<T: Entity>() -> Select<T> { Select { _ghost: PhantomData } }
|
|
|
|
- pub fn update<T: Entity>() -> Update<T> { Update { _ghost: PhantomData } }
|
|
|
|
|
|
+ pub fn get<T: Entity>() -> Select<T> {
|
|
|
|
+ Select {
|
|
|
|
+ _ghost: PhantomData,
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ pub fn update<T: Entity>() -> Update<T> {
|
|
|
|
+ Update {
|
|
|
|
+ _ghost: PhantomData,
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
pub struct Select<T: Entity> {
|
|
pub struct Select<T: Entity> {
|
|
@@ -20,8 +30,19 @@ pub struct Select<T: Entity> {
|
|
pub trait Conditionable: BuildingBlock {
|
|
pub trait Conditionable: BuildingBlock {
|
|
type Table: Entity;
|
|
type Table: Entity;
|
|
|
|
|
|
- fn with<G: Modelable, Col: EntityColumn<Entity = Self::Table>>(self, column: Col, _given: G) -> WhereClause<Self, Col, Self::Table, G> where Self: Sized {
|
|
|
|
- WhereClause { conditionable: self, column, _ghost: PhantomData }
|
|
|
|
|
|
+ fn with<G: Modelable, Col: EntityColumn<Entity = Self::Table>>(
|
|
|
|
+ self,
|
|
|
|
+ column: Col,
|
|
|
|
+ _given: G,
|
|
|
|
+ ) -> WhereClause<Self, Col, Self::Table, G>
|
|
|
|
+ where
|
|
|
|
+ Self: Sized,
|
|
|
|
+ {
|
|
|
|
+ WhereClause {
|
|
|
|
+ conditionable: self,
|
|
|
|
+ column,
|
|
|
|
+ _ghost: PhantomData,
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -29,36 +50,71 @@ impl<T: Entity> Conditionable for Select<T> {
|
|
type Table = T;
|
|
type Table = T;
|
|
}
|
|
}
|
|
|
|
|
|
-pub struct WhereClause<S: Conditionable<Table = T>, Col: EntityColumn<Entity = T>, T: Entity, Given: Modelable> {
|
|
|
|
|
|
+pub struct WhereClause<
|
|
|
|
+ S: Conditionable<Table = T>,
|
|
|
|
+ Col: EntityColumn<Entity = T>,
|
|
|
|
+ T: Entity,
|
|
|
|
+ Given: Modelable,
|
|
|
|
+> {
|
|
conditionable: S,
|
|
conditionable: S,
|
|
column: Col,
|
|
column: Col,
|
|
- _ghost: PhantomData<(S,Col,Given)>
|
|
|
|
|
|
+ _ghost: PhantomData<(S, Col, Given)>,
|
|
}
|
|
}
|
|
|
|
|
|
-impl<S: Conditionable<Table = T>, Col: EntityColumn<Entity = T>, T: Entity, Given: Modelable> Conditionable for WhereClause<S, Col, T, Given> {
|
|
|
|
|
|
+impl<S: Conditionable<Table = T>, Col: EntityColumn<Entity = T>, T: Entity, Given: Modelable>
|
|
|
|
+ Conditionable for WhereClause<S, Col, T, Given>
|
|
|
|
+{
|
|
type Table = T;
|
|
type Table = T;
|
|
}
|
|
}
|
|
|
|
|
|
pub trait Joinable: BuildingBlock {
|
|
pub trait Joinable: BuildingBlock {
|
|
type Table: Entity;
|
|
type Table: Entity;
|
|
|
|
|
|
- fn join<BaseColumn: EntityColumn<Entity = Self::Table>, Target: Entity, TargetColumn: EntityColumn<Entity = Target>>(self, base_column: BaseColumn, target_column: TargetColumn) -> JoinClause<Self::Table, Self, BaseColumn, Target, TargetColumn> where Self: Sized {
|
|
|
|
- JoinClause { joinable: self, base_column, target_column, _ghost: PhantomData }
|
|
|
|
|
|
+ fn join<
|
|
|
|
+ BaseColumn: EntityColumn<Entity = Self::Table>,
|
|
|
|
+ Target: Entity,
|
|
|
|
+ TargetColumn: EntityColumn<Entity = Target>,
|
|
|
|
+ >(
|
|
|
|
+ self,
|
|
|
|
+ base_column: BaseColumn,
|
|
|
|
+ target_column: TargetColumn,
|
|
|
|
+ ) -> JoinClause<Self::Table, Self, BaseColumn, Target, TargetColumn>
|
|
|
|
+ where
|
|
|
|
+ Self: Sized,
|
|
|
|
+ {
|
|
|
|
+ JoinClause {
|
|
|
|
+ joinable: self,
|
|
|
|
+ base_column,
|
|
|
|
+ target_column,
|
|
|
|
+ _ghost: PhantomData,
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-pub struct JoinClause<T: Entity, Base: Joinable<Table = T>, BaseColumn: EntityColumn<Entity = T>, Target: Entity, TargetColumn: EntityColumn<Entity = Target>> {
|
|
|
|
|
|
+pub struct JoinClause<
|
|
|
|
+ T: Entity,
|
|
|
|
+ Base: Joinable<Table = T>,
|
|
|
|
+ BaseColumn: EntityColumn<Entity = T>,
|
|
|
|
+ Target: Entity,
|
|
|
|
+ TargetColumn: EntityColumn<Entity = Target>,
|
|
|
|
+> {
|
|
joinable: Base,
|
|
joinable: Base,
|
|
base_column: BaseColumn,
|
|
base_column: BaseColumn,
|
|
target_column: TargetColumn,
|
|
target_column: TargetColumn,
|
|
- _ghost: PhantomData<(Base, BaseColumn, Target, TargetColumn)>
|
|
|
|
|
|
+ _ghost: PhantomData<(Base, BaseColumn, Target, TargetColumn)>,
|
|
}
|
|
}
|
|
|
|
|
|
impl<T: Entity> Joinable for Select<T> {
|
|
impl<T: Entity> Joinable for Select<T> {
|
|
type Table = T;
|
|
type Table = T;
|
|
}
|
|
}
|
|
|
|
|
|
-impl<S: Joinable + Conditionable<Table = T>, T: Entity, Col: EntityColumn<Entity = T>, Given: Modelable> Joinable for WhereClause<S, Col, T, Given> {
|
|
|
|
|
|
+impl<
|
|
|
|
+ S: Joinable + Conditionable<Table = T>,
|
|
|
|
+ T: Entity,
|
|
|
|
+ Col: EntityColumn<Entity = T>,
|
|
|
|
+ Given: Modelable,
|
|
|
|
+ > Joinable for WhereClause<S, Col, T, Given>
|
|
|
|
+{
|
|
type Table = T;
|
|
type Table = T;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -77,22 +133,39 @@ impl<T: Entity> Settable for Update<T> {
|
|
pub trait Settable {
|
|
pub trait Settable {
|
|
type Table: Entity;
|
|
type Table: Entity;
|
|
|
|
|
|
- fn update<G: Modelable, Col: EntityColumn<Entity = Self::Table>>(self, column: Col, _given: G) -> SetClause<Self, Col, Self::Table, G> where Self: Sized {
|
|
|
|
- SetClause { settable: self, column, _ghost: (PhantomData, PhantomData, PhantomData) }
|
|
|
|
|
|
+ fn update<G: Modelable, Col: EntityColumn<Entity = Self::Table>>(
|
|
|
|
+ self,
|
|
|
|
+ column: Col,
|
|
|
|
+ _given: G,
|
|
|
|
+ ) -> SetClause<Self, Col, Self::Table, G>
|
|
|
|
+ where
|
|
|
|
+ Self: Sized,
|
|
|
|
+ {
|
|
|
|
+ SetClause {
|
|
|
|
+ settable: self,
|
|
|
|
+ column,
|
|
|
|
+ _ghost: (PhantomData, PhantomData, PhantomData),
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-pub struct SetClause<S: Settable<Table = T>, Col: EntityColumn<Entity = T>, T: Entity, Given: Modelable> {
|
|
|
|
|
|
+pub struct SetClause<
|
|
|
|
+ S: Settable<Table = T>,
|
|
|
|
+ Col: EntityColumn<Entity = T>,
|
|
|
|
+ T: Entity,
|
|
|
|
+ Given: Modelable,
|
|
|
|
+> {
|
|
settable: S,
|
|
settable: S,
|
|
column: Col,
|
|
column: Col,
|
|
- _ghost: (PhantomData<S>, PhantomData<Col>, PhantomData<Given>)
|
|
|
|
|
|
+ _ghost: (PhantomData<S>, PhantomData<Col>, PhantomData<Given>),
|
|
}
|
|
}
|
|
|
|
|
|
-impl<S: Settable<Table = T>, Col: EntityColumn<Entity = T>, T: Entity, Given: Modelable> Conditionable for SetClause<S, Col, T, Given> {
|
|
|
|
|
|
+impl<S: Settable<Table = T>, Col: EntityColumn<Entity = T>, T: Entity, Given: Modelable>
|
|
|
|
+ Conditionable for SetClause<S, Col, T, Given>
|
|
|
|
+{
|
|
type Table = T;
|
|
type Table = T;
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
// BuildingBlock implementations
|
|
// BuildingBlock implementations
|
|
impl<T: Entity> BuildingBlock for Select<T> {
|
|
impl<T: Entity> BuildingBlock for Select<T> {
|
|
fn build_query(&self) -> String {
|
|
fn build_query(&self) -> String {
|
|
@@ -100,21 +173,36 @@ impl<T: Entity> BuildingBlock for Select<T> {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-impl<S: Conditionable<Table = T>, Col: EntityColumn<Entity = T>, T: Entity, Given: Modelable> BuildingBlock for WhereClause<S, Col, T, Given> {
|
|
|
|
|
|
+impl<S: Conditionable<Table = T>, Col: EntityColumn<Entity = T>, T: Entity, Given: Modelable>
|
|
|
|
+ BuildingBlock for WhereClause<S, Col, T, Given>
|
|
|
|
+{
|
|
fn build_query(&self) -> String {
|
|
fn build_query(&self) -> String {
|
|
- format!("{} AND {} = ?", self.conditionable.build_query(), self.column.name())
|
|
|
|
|
|
+ format!(
|
|
|
|
+ "{} AND {} = ?",
|
|
|
|
+ self.conditionable.build_query(),
|
|
|
|
+ self.column.name()
|
|
|
|
+ )
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-impl<T: Entity, Base: Joinable<Table = T>, BaseColumn: EntityColumn<Entity = T>, Target: Entity, TargetColumn: EntityColumn<Entity = Target>> BuildingBlock for JoinClause<T, Base, BaseColumn, Target, TargetColumn> {
|
|
|
|
|
|
+impl<
|
|
|
|
+ T: Entity,
|
|
|
|
+ Base: Joinable<Table = T>,
|
|
|
|
+ BaseColumn: EntityColumn<Entity = T>,
|
|
|
|
+ Target: Entity,
|
|
|
|
+ TargetColumn: EntityColumn<Entity = Target>,
|
|
|
|
+ > BuildingBlock for JoinClause<T, Base, BaseColumn, Target, TargetColumn>
|
|
|
|
+{
|
|
fn build_query(&self) -> String {
|
|
fn build_query(&self) -> String {
|
|
- format!("{} JOIN {} ON {}.{} = {}.{}",
|
|
|
|
|
|
+ format!(
|
|
|
|
+ "{} JOIN {} ON {}.{} = {}.{}",
|
|
self.joinable.build_query(),
|
|
self.joinable.build_query(),
|
|
self.target_column.table_name(),
|
|
self.target_column.table_name(),
|
|
self.base_column.table_name(),
|
|
self.base_column.table_name(),
|
|
self.base_column.name(),
|
|
self.base_column.name(),
|
|
self.target_column.table_name(),
|
|
self.target_column.table_name(),
|
|
- self.target_column.name())
|
|
|
|
|
|
+ self.target_column.name()
|
|
|
|
+ )
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -124,7 +212,9 @@ impl<T: Entity> BuildingBlock for Update<T> {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-impl<S: Settable<Table = T>, Col: EntityColumn<Entity = T>, T: Entity, Given: Modelable> BuildingBlock for SetClause<S, Col, T, Given> {
|
|
|
|
|
|
+impl<S: Settable<Table = T>, Col: EntityColumn<Entity = T>, T: Entity, Given: Modelable>
|
|
|
|
+ BuildingBlock for SetClause<S, Col, T, Given>
|
|
|
|
+{
|
|
fn build_query(&self) -> String {
|
|
fn build_query(&self) -> String {
|
|
//format!("UPDATE {} SET {} = ? WHERE true", T::table_name(), self.column.name())
|
|
//format!("UPDATE {} SET {} = ? WHERE true", T::table_name(), self.column.name())
|
|
format!("<>")
|
|
format!("<>")
|
|
@@ -139,23 +229,41 @@ mod builder_test {
|
|
#[microrm_internal]
|
|
#[microrm_internal]
|
|
pub struct SimpleEntity {
|
|
pub struct SimpleEntity {
|
|
a: usize,
|
|
a: usize,
|
|
- b: usize
|
|
|
|
|
|
+ b: usize,
|
|
}
|
|
}
|
|
|
|
|
|
#[derive(crate::Entity, serde::Deserialize, serde::Serialize)]
|
|
#[derive(crate::Entity, serde::Deserialize, serde::Serialize)]
|
|
#[microrm_internal]
|
|
#[microrm_internal]
|
|
pub struct ChildType {
|
|
pub struct ChildType {
|
|
r: SimpleEntityID,
|
|
r: SimpleEntityID,
|
|
- b: usize
|
|
|
|
|
|
+ b: usize,
|
|
}
|
|
}
|
|
|
|
|
|
#[test]
|
|
#[test]
|
|
fn simple_builder_select_test() {
|
|
fn simple_builder_select_test() {
|
|
println!("{}", Builder::get::<SimpleEntity>().build_query());
|
|
println!("{}", Builder::get::<SimpleEntity>().build_query());
|
|
- println!("{}", Builder::get::<SimpleEntity>().with(SimpleEntity::A, 0u8).with(SimpleEntity::B, 1u8).build_query());
|
|
|
|
-
|
|
|
|
- println!("{}", Builder::get::<SimpleEntity>().with(SimpleEntity::A, 0u8).join(SimpleEntity::ID, ChildType::R).build_query());
|
|
|
|
-
|
|
|
|
- println!("{}", Builder::update::<SimpleEntity>().update(SimpleEntity::A, 1u8).with(SimpleEntity::ID, 1u8).build_query());
|
|
|
|
|
|
+ println!(
|
|
|
|
+ "{}",
|
|
|
|
+ Builder::get::<SimpleEntity>()
|
|
|
|
+ .with(SimpleEntity::A, 0u8)
|
|
|
|
+ .with(SimpleEntity::B, 1u8)
|
|
|
|
+ .build_query()
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ println!(
|
|
|
|
+ "{}",
|
|
|
|
+ Builder::get::<SimpleEntity>()
|
|
|
|
+ .with(SimpleEntity::A, 0u8)
|
|
|
|
+ .join(SimpleEntity::ID, ChildType::R)
|
|
|
|
+ .build_query()
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ println!(
|
|
|
|
+ "{}",
|
|
|
|
+ Builder::update::<SimpleEntity>()
|
|
|
|
+ .update(SimpleEntity::A, 1u8)
|
|
|
|
+ .with(SimpleEntity::ID, 1u8)
|
|
|
|
+ .build_query()
|
|
|
|
+ );
|
|
}
|
|
}
|
|
}
|
|
}
|