From 6289b331a98dc13808a1ae252ae175790e2be464 Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Sun, 9 May 2021 15:28:03 +0800 Subject: [PATCH] Model getter and setter --- src/entity/column.rs | 10 ++++++- src/entity/model.rs | 12 ++++++-- src/query/result.rs | 67 ++++++++++++++++++++++++------------------ src/tests_cfg/cake.rs | 37 +++++++++++++++++++---- src/tests_cfg/fruit.rs | 42 ++++++++++++++++++++++---- 5 files changed, 125 insertions(+), 43 deletions(-) diff --git a/src/entity/column.rs b/src/entity/column.rs index 2e9073d2..bf4d1c64 100644 --- a/src/entity/column.rs +++ b/src/entity/column.rs @@ -15,7 +15,15 @@ macro_rules! bind_oper { }; } -pub trait ColumnTrait: Iden + Copy + Debug + 'static { +pub trait IdenStatic: Iden + Copy + Debug + 'static { + fn as_str(&self) -> &str; + + fn unquoted(&self, s: &mut dyn std::fmt::Write) { + write!(s, "{}", self.as_str()).unwrap(); + } +} + +pub trait ColumnTrait: IdenStatic { type Entity: EntityTrait; fn def(&self) -> ColumnType; diff --git a/src/entity/model.rs b/src/entity/model.rs index 98e2d6ac..f86a63d8 100644 --- a/src/entity/model.rs +++ b/src/entity/model.rs @@ -1,6 +1,14 @@ -use crate::{QueryResult, TypeErr}; +use crate::{ColumnTrait, QueryResult, TypeErr}; +pub use sea_query::Value; +use std::fmt::Debug; + +pub trait ModelTrait: Clone + Debug + Default { + type Column: ColumnTrait; + + fn get(&self, c: Self::Column) -> Value; + + fn set(&mut self, c: Self::Column, v: Value); -pub trait ModelTrait { fn from_query_result(row: QueryResult) -> Result where Self: std::marker::Sized; diff --git a/src/query/result.rs b/src/query/result.rs index c9c9d112..fb72349a 100644 --- a/src/query/result.rs +++ b/src/query/result.rs @@ -17,32 +17,52 @@ pub struct TypeErr; pub trait TryGetable { fn try_get(res: &QueryResult, col: &str) -> Result where - Self: std::marker::Sized; + Self: Sized; } // TryGetable // -impl TryGetable for i32 { - fn try_get(res: &QueryResult, col: &str) -> Result { - match &res.row { - QueryResultRow::SqlxMySql(row) => { - use sqlx::Row; - Ok(row.try_get(col)?) +macro_rules! try_getable { + ( $type: ty ) => { + impl TryGetable for $type { + fn try_get(res: &QueryResult, col: &str) -> Result { + match &res.row { + QueryResultRow::SqlxMySql(row) => { + use sqlx::Row; + Ok(row.try_get(col)?) + } + } } } - } + + impl TryGetable for Option<$type> { + fn try_get(res: &QueryResult, col: &str) -> Result { + match &res.row { + QueryResultRow::SqlxMySql(row) => { + use sqlx::Row; + match row.try_get(col) { + Ok(v) => Ok(Some(v)), + Err(_) => Ok(None), + } + } + } + } + } + }; } -impl TryGetable for String { - fn try_get(res: &QueryResult, col: &str) -> Result { - match &res.row { - QueryResultRow::SqlxMySql(row) => { - use sqlx::Row; - Ok(row.try_get(col)?) - } - } - } -} +try_getable!(bool); +try_getable!(i8); +try_getable!(i16); +try_getable!(i32); +try_getable!(i64); +try_getable!(u8); +try_getable!(u16); +try_getable!(u32); +try_getable!(u64); +try_getable!(f32); +try_getable!(f64); +try_getable!(String); // QueryResult // @@ -53,17 +73,6 @@ impl QueryResult { { T::try_get(self, col) } - - pub fn try_get_option(&self, col: &str) -> Result, TypeErr> - where - T: TryGetable, - { - if let Ok(v) = T::try_get(self, col) { - Ok(Some(v)) - } else { - Ok(None) - } - } } // TypeErr // diff --git a/src/tests_cfg/cake.rs b/src/tests_cfg/cake.rs index f3906711..6722e0c8 100644 --- a/src/tests_cfg/cake.rs +++ b/src/tests_cfg/cake.rs @@ -1,13 +1,13 @@ use crate::{ - ColumnTrait, ColumnType, EntityTrait, EnumIter, Iden, Identity, IntoIdentity, ModelTrait, - QueryResult, Related, RelationDef, RelationTrait, Select, TypeErr, + ColumnTrait, ColumnType, EntityTrait, EnumIter, Iden, IdenStatic, Identity, IntoIdentity, + ModelTrait, QueryResult, Related, RelationDef, RelationTrait, Select, TypeErr, Value, }; #[derive(Default, Debug, Iden)] #[iden = "cake"] pub struct Entity; -#[derive(Debug, Default, PartialEq)] +#[derive(Clone, Debug, Default, PartialEq)] pub struct Model { pub id: i32, pub name: String, @@ -36,15 +36,42 @@ impl EntityTrait for Entity { } } +// TODO: implement with derive macro impl ModelTrait for Model { + type Column = Column; + + fn get(&self, c: Self::Column) -> Value { + match c { + Column::Id => self.id.clone().into(), + Column::Name => self.name.clone().into(), + } + } + + fn set(&mut self, c: Self::Column, v: Value) { + match c { + Column::Id => self.id = v.unwrap(), + Column::Name => self.name = v.unwrap(), + } + } + fn from_query_result(row: QueryResult) -> Result { Ok(Self { - id: row.try_get("id")?, - name: row.try_get("name")?, + id: row.try_get(Column::Id.as_str())?, + name: row.try_get(Column::Name.as_str())?, }) } } +// TODO: implement with derive macro +impl IdenStatic for Column { + fn as_str(&self) -> &str { + match self { + Column::Id => "id", + Column::Name => "name", + } + } +} + impl ColumnTrait for Column { type Entity = Entity; diff --git a/src/tests_cfg/fruit.rs b/src/tests_cfg/fruit.rs index 3bdd40d4..8e595394 100644 --- a/src/tests_cfg/fruit.rs +++ b/src/tests_cfg/fruit.rs @@ -1,13 +1,13 @@ use crate::{ - ColumnTrait, ColumnType, EntityTrait, EnumIter, Iden, Identity, IntoIdentity, ModelTrait, - QueryResult, RelationDef, RelationTrait, TypeErr, + ColumnTrait, ColumnType, EntityTrait, EnumIter, Iden, IdenStatic, Identity, IntoIdentity, + ModelTrait, QueryResult, RelationDef, RelationTrait, TypeErr, Value, }; #[derive(Default, Debug, Iden)] #[iden = "fruit"] pub struct Entity; -#[derive(Debug, Default, PartialEq)] +#[derive(Clone, Debug, Default, PartialEq)] pub struct Model { pub id: i32, pub name: String, @@ -36,16 +36,46 @@ impl EntityTrait for Entity { } } +// TODO: implement with derive macro impl ModelTrait for Model { + type Column = Column; + + fn get(&self, c: Self::Column) -> Value { + match c { + Column::Id => self.id.clone().into(), + Column::Name => self.name.clone().into(), + Column::CakeId => self.cake_id.clone().into(), + } + } + + fn set(&mut self, c: Self::Column, v: Value) { + match c { + Column::Id => self.id = v.unwrap(), + Column::Name => self.name = v.unwrap(), + Column::CakeId => self.cake_id = v.unwrap(), + } + } + fn from_query_result(row: QueryResult) -> Result { Ok(Self { - id: row.try_get("id")?, - name: row.try_get("name")?, - cake_id: row.try_get_option("cake_id")?, + id: row.try_get(Column::Id.as_str())?, + name: row.try_get(Column::Name.as_str())?, + cake_id: row.try_get(Column::CakeId.as_str())?, }) } } +// TODO: implement with derive macro +impl IdenStatic for Column { + fn as_str(&self) -> &str { + match self { + Column::Id => "id", + Column::Name => "name", + Column::CakeId => "cake_id", + } + } +} + impl ColumnTrait for Column { type Entity = Entity;