|
@@ -1,9 +1,12 @@
|
|
|
|
+use std::any::Any;
|
|
|
|
+use std::hash::Hash;
|
|
|
|
+
|
|
use crate::entity::{Entity, EntityColumn, EntityID};
|
|
use crate::entity::{Entity, EntityColumn, EntityID};
|
|
use crate::model::Modelable;
|
|
use crate::model::Modelable;
|
|
|
|
|
|
// pub mod expr;
|
|
// pub mod expr;
|
|
// pub mod condition;
|
|
// pub mod condition;
|
|
-// pub mod builder;
|
|
|
|
|
|
+pub mod builder;
|
|
|
|
|
|
/// Wraps an entity with its ID, for example as a query result.
|
|
/// Wraps an entity with its ID, for example as a query result.
|
|
///
|
|
///
|
|
@@ -122,7 +125,6 @@ impl<'l> QueryInterface<'l> {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-/*
|
|
|
|
impl<'l> QueryInterface<'l> {
|
|
impl<'l> QueryInterface<'l> {
|
|
fn cached_query<Return>(
|
|
fn cached_query<Return>(
|
|
&self,
|
|
&self,
|
|
@@ -139,11 +141,11 @@ impl<'l> QueryInterface<'l> {
|
|
with(query)
|
|
with(query)
|
|
}
|
|
}
|
|
|
|
|
|
- fn cached_query_column<Column: EntityColumn, Return>(
|
|
|
|
|
|
+ fn cached_query_column<T: Entity, Return>(
|
|
&self,
|
|
&self,
|
|
context: &'static str,
|
|
context: &'static str,
|
|
ty: std::any::TypeId,
|
|
ty: std::any::TypeId,
|
|
- variant: &[Column],
|
|
|
|
|
|
+ variant: &[&dyn EntityColumn<Entity = T>],
|
|
create: &dyn Fn() -> sqlite::Statement<'l>,
|
|
create: &dyn Fn() -> sqlite::Statement<'l>,
|
|
with: &mut dyn FnMut(&mut sqlite::Statement<'l>) -> Return,
|
|
with: &mut dyn FnMut(&mut sqlite::Statement<'l>) -> Return,
|
|
) -> Return {
|
|
) -> Return {
|
|
@@ -151,7 +153,7 @@ impl<'l> QueryInterface<'l> {
|
|
|
|
|
|
let mut hasher = std::collections::hash_map::DefaultHasher::new();
|
|
let mut hasher = std::collections::hash_map::DefaultHasher::new();
|
|
for v in variant {
|
|
for v in variant {
|
|
- v.hash(&mut hasher);
|
|
|
|
|
|
+ v.column_typeid().hash(&mut hasher);
|
|
}
|
|
}
|
|
let hash = hasher.finish();
|
|
let hash = hasher.finish();
|
|
|
|
|
|
@@ -163,23 +165,23 @@ impl<'l> QueryInterface<'l> {
|
|
with(query)
|
|
with(query)
|
|
}
|
|
}
|
|
|
|
|
|
- /*
|
|
|
|
|
|
|
|
/// Search for an entity by a property
|
|
/// Search for an entity by a property
|
|
pub fn get_one_by<
|
|
pub fn get_one_by<
|
|
- C: EntityColumn
|
|
|
|
|
|
+ C: EntityColumn,
|
|
|
|
+ V: Modelable
|
|
>(
|
|
>(
|
|
&self,
|
|
&self,
|
|
- val: &dyn Modelable,
|
|
|
|
|
|
+ col: C,
|
|
|
|
+ val: V
|
|
) -> Option<WithID<C::Entity>> {
|
|
) -> Option<WithID<C::Entity>> {
|
|
let table_name = <C::Entity>::table_name();
|
|
let table_name = <C::Entity>::table_name();
|
|
- let column_name = C::name();
|
|
|
|
- // let column_name = <T as Entity>::name(c.clone());
|
|
|
|
|
|
+ let column_name = col.name();
|
|
|
|
|
|
self.cached_query_column(
|
|
self.cached_query_column(
|
|
"get_one_by",
|
|
"get_one_by",
|
|
- std::any::TypeId::of::<usize>(), // XXX
|
|
|
|
- &[],// XXX
|
|
|
|
|
|
+ std::any::TypeId::of::<C::Entity>(),
|
|
|
|
+ &[&col],
|
|
&|| {
|
|
&|| {
|
|
self.db
|
|
self.db
|
|
.conn
|
|
.conn
|
|
@@ -200,30 +202,28 @@ impl<'l> QueryInterface<'l> {
|
|
)
|
|
)
|
|
}
|
|
}
|
|
|
|
|
|
- /*
|
|
|
|
/// Search for an entity by multiple properties
|
|
/// Search for an entity by multiple properties
|
|
pub fn get_one_by_multi<
|
|
pub fn get_one_by_multi<
|
|
- T: Entity<Column = C>,
|
|
|
|
- C: EntityColumn<Entity = T>,
|
|
|
|
|
|
+ C: EntityColumn,
|
|
>(
|
|
>(
|
|
&self,
|
|
&self,
|
|
- c: &[C],
|
|
|
|
|
|
+ c: &[&dyn EntityColumn<Entity = C::Entity>],
|
|
val: &[&dyn crate::model::Modelable],
|
|
val: &[&dyn crate::model::Modelable],
|
|
- ) -> Option<WithID<T>> {
|
|
|
|
- let table_name = <T as Entity>::table_name();
|
|
|
|
|
|
+ ) -> Option<WithID<C::Entity>> {
|
|
|
|
+ let table_name = <C::Entity as Entity>::table_name();
|
|
|
|
|
|
assert_eq!(c.len(), val.len());
|
|
assert_eq!(c.len(), val.len());
|
|
|
|
|
|
self.cached_query_column(
|
|
self.cached_query_column(
|
|
"get_one_by_multi",
|
|
"get_one_by_multi",
|
|
- std::any::TypeId::of::<T>(),
|
|
|
|
|
|
+ std::any::TypeId::of::<C::Entity>(),
|
|
c,
|
|
c,
|
|
&|| {
|
|
&|| {
|
|
let query = format!(
|
|
let query = format!(
|
|
"SELECT * FROM \"{}\" WHERE {}",
|
|
"SELECT * FROM \"{}\" WHERE {}",
|
|
table_name,
|
|
table_name,
|
|
c.iter()
|
|
c.iter()
|
|
- .map(|col| format!("\"{}\" = ?", <T as Entity>::name(col.clone())))
|
|
|
|
|
|
+ .map(|col| format!("\"{}\" = ?", col.name()))
|
|
.collect::<Vec<_>>()
|
|
.collect::<Vec<_>>()
|
|
.join(" AND ")
|
|
.join(" AND ")
|
|
);
|
|
);
|
|
@@ -239,30 +239,28 @@ impl<'l> QueryInterface<'l> {
|
|
|
|
|
|
self.expect_one_result(stmt, &mut |stmt| {
|
|
self.expect_one_result(stmt, &mut |stmt| {
|
|
let id: i64 = stmt.read(0).ok()?;
|
|
let id: i64 = stmt.read(0).ok()?;
|
|
- Some(WithID::wrap(T::build_from(stmt).ok()?, id))
|
|
|
|
|
|
+ Some(WithID::wrap(C::Entity::build_from(stmt).ok()?, id))
|
|
})
|
|
})
|
|
},
|
|
},
|
|
)
|
|
)
|
|
}
|
|
}
|
|
- */
|
|
|
|
|
|
|
|
/// Delete entities by searching with a single property
|
|
/// Delete entities by searching with a single property
|
|
pub fn delete_by<
|
|
pub fn delete_by<
|
|
- T: Entity<Column = C>,
|
|
|
|
- C: EntityColumns<Entity = T>,
|
|
|
|
- V: crate::model::Modelable
|
|
|
|
|
|
+ C: EntityColumn,
|
|
|
|
+ V: Modelable
|
|
>(
|
|
>(
|
|
&self,
|
|
&self,
|
|
c: C,
|
|
c: C,
|
|
val: V
|
|
val: V
|
|
) -> Option<()> {
|
|
) -> Option<()> {
|
|
- let table_name = <T as Entity>::table_name();
|
|
|
|
- let column_name = <C as EntityColumn>::name();
|
|
|
|
|
|
+ let table_name = <C::Entity>::table_name();
|
|
|
|
+ let column_name = c.name();
|
|
|
|
|
|
self.cached_query_column(
|
|
self.cached_query_column(
|
|
"delete_by",
|
|
"delete_by",
|
|
- std::any::TypeId::of::<T>(),
|
|
|
|
- &[c],
|
|
|
|
|
|
+ std::any::TypeId::of::<C::Entity>(),
|
|
|
|
+ &[&c],
|
|
&|| {
|
|
&|| {
|
|
let query = format!(
|
|
let query = format!(
|
|
"DELETE FROM \"{}\" WHERE {} = ?",
|
|
"DELETE FROM \"{}\" WHERE {} = ?",
|
|
@@ -311,16 +309,16 @@ impl<'l> QueryInterface<'l> {
|
|
)
|
|
)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
/// Delete entities by searching with multiple properties
|
|
/// Delete entities by searching with multiple properties
|
|
pub fn delete_by_multi<
|
|
pub fn delete_by_multi<
|
|
- T: Entity<Column = C>,
|
|
|
|
- C: EntityColumns<Entity = T>,
|
|
|
|
|
|
+ T: Entity
|
|
>(
|
|
>(
|
|
&self,
|
|
&self,
|
|
- c: &[C],
|
|
|
|
|
|
+ c: &[&dyn EntityColumn<Entity = T>],
|
|
val: &[&dyn crate::model::Modelable],
|
|
val: &[&dyn crate::model::Modelable],
|
|
) -> Option<()> {
|
|
) -> Option<()> {
|
|
- let table_name = <T as Entity>::table_name();
|
|
|
|
|
|
+ let table_name = <T>::table_name();
|
|
|
|
|
|
assert_eq!(c.len(), val.len());
|
|
assert_eq!(c.len(), val.len());
|
|
|
|
|
|
@@ -333,7 +331,7 @@ impl<'l> QueryInterface<'l> {
|
|
"DELETE FROM \"{}\" WHERE {}",
|
|
"DELETE FROM \"{}\" WHERE {}",
|
|
table_name,
|
|
table_name,
|
|
c.iter()
|
|
c.iter()
|
|
- .map(|col| format!("\"{}\" = ?", <T as Entity>::name(col.clone())))
|
|
|
|
|
|
+ .map(|col| format!("\"{}\" = ?", col.name()))
|
|
.collect::<Vec<_>>()
|
|
.collect::<Vec<_>>()
|
|
.join(" AND ")
|
|
.join(" AND ")
|
|
);
|
|
);
|
|
@@ -378,21 +376,20 @@ impl<'l> QueryInterface<'l> {
|
|
|
|
|
|
/// Search for all entities matching a property
|
|
/// Search for all entities matching a property
|
|
pub fn get_all_by<
|
|
pub fn get_all_by<
|
|
- T: Entity<Column = C>,
|
|
|
|
- C: EntityColumns<Entity = T>,
|
|
|
|
- V: crate::model::Modelable,
|
|
|
|
|
|
+ C: EntityColumn,
|
|
|
|
+ V: Modelable,
|
|
>(
|
|
>(
|
|
&self,
|
|
&self,
|
|
c: C,
|
|
c: C,
|
|
val: V,
|
|
val: V,
|
|
- ) -> Option<Vec<WithID<T>>> {
|
|
|
|
- let table_name = <T as Entity>::table_name();
|
|
|
|
- let column_name = <C as EntityColumn>::name();
|
|
|
|
|
|
+ ) -> Option<Vec<WithID<C::Entity>>> {
|
|
|
|
+ let table_name = <C::Entity>::table_name();
|
|
|
|
+ let column_name = c.name();
|
|
|
|
|
|
self.cached_query_column(
|
|
self.cached_query_column(
|
|
"get_all_by",
|
|
"get_all_by",
|
|
- std::any::TypeId::of::<T>(),
|
|
|
|
- &[c],
|
|
|
|
|
|
+ std::any::TypeId::of::<C::Entity>(),
|
|
|
|
+ &[&c],
|
|
&|| {
|
|
&|| {
|
|
self.db
|
|
self.db
|
|
.conn
|
|
.conn
|
|
@@ -413,7 +410,7 @@ impl<'l> QueryInterface<'l> {
|
|
}
|
|
}
|
|
|
|
|
|
let id: i64 = stmt.read(0).ok()?;
|
|
let id: i64 = stmt.read(0).ok()?;
|
|
- res.push(WithID::wrap(T::build_from(stmt).ok()?, id));
|
|
|
|
|
|
+ res.push(WithID::wrap(C::Entity::build_from(stmt).ok()?, id));
|
|
}
|
|
}
|
|
|
|
|
|
Some(res)
|
|
Some(res)
|
|
@@ -424,7 +421,7 @@ impl<'l> QueryInterface<'l> {
|
|
/// Add an entity to its table
|
|
/// Add an entity to its table
|
|
pub fn add<T: Entity + serde::Serialize>(&self, m: &T) -> Option<<T as Entity>::ID> {
|
|
pub fn add<T: Entity + serde::Serialize>(&self, m: &T) -> Option<<T as Entity>::ID> {
|
|
self.cached_query(
|
|
self.cached_query(
|
|
- "get_all_by",
|
|
|
|
|
|
+ "add",
|
|
std::any::TypeId::of::<T>(),
|
|
std::any::TypeId::of::<T>(),
|
|
&|| {
|
|
&|| {
|
|
let placeholders = (0..(<T as Entity>::column_count() - 1))
|
|
let placeholders = (0..(<T as Entity>::column_count() - 1))
|
|
@@ -450,6 +447,4 @@ impl<'l> QueryInterface<'l> {
|
|
},
|
|
},
|
|
)
|
|
)
|
|
}
|
|
}
|
|
- */
|
|
|
|
}
|
|
}
|
|
-*/
|
|
|