|
@@ -1,57 +1,66 @@
|
|
|
use crate::DB;
|
|
|
+use crate::model::{Entity,EntityID,EntityColumns};
|
|
|
|
|
|
pub mod condition;
|
|
|
|
|
|
-pub type ID = i64;
|
|
|
-
|
|
|
+/// Wraps an entity with its ID, for example as a query result.
|
|
|
+///
|
|
|
+/// The wrapped value is accessible via `Deref`, so this should be mostly
|
|
|
+/// transparent.
|
|
|
#[derive(Debug)]
|
|
|
-pub struct WithID<T: crate::model::Entity> {
|
|
|
+pub struct WithID<T: Entity> {
|
|
|
wrap: T,
|
|
|
- id: ID,
|
|
|
+ id: <T as Entity>::ID
|
|
|
}
|
|
|
|
|
|
-impl<T: crate::model::Entity> WithID<T> {
|
|
|
+impl<T: Entity> WithID<T> {
|
|
|
fn wrap(what: T, raw_id: i64) -> Self {
|
|
|
Self {
|
|
|
wrap: what,
|
|
|
- id: raw_id
|
|
|
+ id: <T as Entity>::ID::from_raw_id(raw_id)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-impl<T: crate::model::Entity> WithID<T> {
|
|
|
- pub fn id(&self) -> ID {
|
|
|
+impl<T: Entity> WithID<T> {
|
|
|
+ pub fn id(&self) -> <T as Entity>::ID {
|
|
|
self.id
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-impl<T: crate::model::Entity> AsRef<T> for WithID<T> {
|
|
|
+impl<T: Entity> AsRef<T> for WithID<T> {
|
|
|
fn as_ref(&self) -> &T {
|
|
|
&self.wrap
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-impl<T: crate::model::Entity> std::ops::Deref for WithID<T> {
|
|
|
+impl<T: Entity> std::ops::Deref for WithID<T> {
|
|
|
type Target = T;
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
&self.wrap
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-impl<T: crate::model::Entity> std::ops::DerefMut for WithID<T> {
|
|
|
+impl<T: Entity> std::ops::DerefMut for WithID<T> {
|
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
|
&mut self.wrap
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/*impl<T: Entity> std::convert::Into<T> for WithID<T> {
|
|
|
+ fn into(self) -> T {
|
|
|
+ self.wrap
|
|
|
+ }
|
|
|
+}*/
|
|
|
+
|
|
|
/// Search for an entity by a property
|
|
|
-pub fn get_one_by<T: crate::model::Entity<Column = C>, C: crate::model::EntityColumns<Entity = T>, V: rusqlite::ToSql>(
|
|
|
+pub fn get_one_by<T: Entity<Column = C>, C: EntityColumns<Entity = T>, V: rusqlite::ToSql>(
|
|
|
db: &DB,
|
|
|
c: C,
|
|
|
val: V,
|
|
|
) -> Option<WithID<T>> {
|
|
|
- let table_name = <T as crate::model::Entity>::table_name();
|
|
|
- let column_name = <T as crate::model::Entity>::name(c);
|
|
|
+ let table_name = <T as Entity>::table_name();
|
|
|
+ let column_name = <T as Entity>::name(c);
|
|
|
let mut prepared = db
|
|
|
.conn
|
|
|
.prepare(&format!(
|
|
@@ -72,13 +81,13 @@ pub fn get_one_by<T: crate::model::Entity<Column = C>, C: crate::model::EntityCo
|
|
|
}
|
|
|
|
|
|
/// Search for all entities matching a property
|
|
|
-pub fn get_all_by<T: crate::model::Entity<Column = C>, C: crate::model::EntityColumns<Entity = T>, V: rusqlite::ToSql>(
|
|
|
+pub fn get_all_by<T: Entity<Column = C>, C: EntityColumns<Entity = T>, V: rusqlite::ToSql>(
|
|
|
db: &DB,
|
|
|
c: C,
|
|
|
val: V) -> Option<Vec<WithID<T>>> {
|
|
|
|
|
|
- let table_name = <T as crate::model::Entity>::table_name();
|
|
|
- let column_name = <T as crate::model::Entity>::name(c);
|
|
|
+ let table_name = <T as Entity>::table_name();
|
|
|
+ let column_name = <T as Entity>::name(c);
|
|
|
|
|
|
let mut prepared = db
|
|
|
.conn
|
|
@@ -99,11 +108,11 @@ pub fn get_all_by<T: crate::model::Entity<Column = C>, C: crate::model::EntityCo
|
|
|
}
|
|
|
|
|
|
/// Search for an entity by ID
|
|
|
-pub fn get_one_by_id<T: crate::model::Entity>(
|
|
|
+pub fn get_one_by_id<T: Entity>(
|
|
|
db: &DB,
|
|
|
- id: ID
|
|
|
+ id: <T as Entity>::ID
|
|
|
) -> Option<WithID<T>> {
|
|
|
- let table_name = <T as crate::model::Entity>::table_name();
|
|
|
+ let table_name = <T as Entity>::table_name();
|
|
|
let mut prepared = db
|
|
|
.conn
|
|
|
.prepare(&format!(
|
|
@@ -124,24 +133,24 @@ pub fn get_one_by_id<T: crate::model::Entity>(
|
|
|
}
|
|
|
|
|
|
/// Add an entity to its table
|
|
|
-pub fn add<T: crate::model::Entity + serde::Serialize>(db: &DB, m: &T) -> Option<ID> {
|
|
|
+pub fn add<T: Entity + serde::Serialize>(db: &DB, m: &T) -> Option<<T as Entity>::ID> {
|
|
|
let row = crate::model::store::serialize_as_row(m);
|
|
|
|
|
|
- let placeholders = (0..<T as crate::model::Entity>::column_count())
|
|
|
+ let placeholders = (0..<T as Entity>::column_count())
|
|
|
.map(|n| format!("?{}", n + 1))
|
|
|
.collect::<Vec<_>>()
|
|
|
.join(",");
|
|
|
|
|
|
let res = db.conn.prepare(&format!(
|
|
|
"INSERT INTO \"{}\" VALUES ({})",
|
|
|
- <T as crate::model::Entity>::table_name(),
|
|
|
+ <T as Entity>::table_name(),
|
|
|
placeholders
|
|
|
));
|
|
|
let mut prepared = res.ok()?;
|
|
|
|
|
|
// make sure we bound enough things
|
|
|
- assert_eq!(row.len(), <T as crate::model::Entity>::column_count());
|
|
|
+ assert_eq!(row.len(), <T as Entity>::column_count());
|
|
|
|
|
|
let id = prepared.insert(rusqlite::params_from_iter(row)).ok()?;
|
|
|
- Some(id)
|
|
|
+ Some(<T as Entity>::ID::from_raw_id(id))
|
|
|
}
|