Model getter and setter

This commit is contained in:
Chris Tsang 2021-05-09 15:28:03 +08:00
parent c72d7b0289
commit 6289b331a9
5 changed files with 125 additions and 43 deletions

View File

@ -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; type Entity: EntityTrait;
fn def(&self) -> ColumnType; fn def(&self) -> ColumnType;

View File

@ -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<Self, TypeErr> fn from_query_result(row: QueryResult) -> Result<Self, TypeErr>
where where
Self: std::marker::Sized; Self: std::marker::Sized;

View File

@ -17,12 +17,14 @@ pub struct TypeErr;
pub trait TryGetable { pub trait TryGetable {
fn try_get(res: &QueryResult, col: &str) -> Result<Self, TypeErr> fn try_get(res: &QueryResult, col: &str) -> Result<Self, TypeErr>
where where
Self: std::marker::Sized; Self: Sized;
} }
// TryGetable // // TryGetable //
impl TryGetable for i32 { macro_rules! try_getable {
( $type: ty ) => {
impl TryGetable for $type {
fn try_get(res: &QueryResult, col: &str) -> Result<Self, TypeErr> { fn try_get(res: &QueryResult, col: &str) -> Result<Self, TypeErr> {
match &res.row { match &res.row {
QueryResultRow::SqlxMySql(row) => { QueryResultRow::SqlxMySql(row) => {
@ -31,18 +33,36 @@ impl TryGetable for i32 {
} }
} }
} }
}
impl TryGetable for Option<$type> {
fn try_get(res: &QueryResult, col: &str) -> Result<Self, TypeErr> {
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 { try_getable!(bool);
fn try_get(res: &QueryResult, col: &str) -> Result<Self, TypeErr> { try_getable!(i8);
match &res.row { try_getable!(i16);
QueryResultRow::SqlxMySql(row) => { try_getable!(i32);
use sqlx::Row; try_getable!(i64);
Ok(row.try_get(col)?) try_getable!(u8);
} try_getable!(u16);
} try_getable!(u32);
} try_getable!(u64);
} try_getable!(f32);
try_getable!(f64);
try_getable!(String);
// QueryResult // // QueryResult //
@ -53,17 +73,6 @@ impl QueryResult {
{ {
T::try_get(self, col) T::try_get(self, col)
} }
pub fn try_get_option<T>(&self, col: &str) -> Result<Option<T>, TypeErr>
where
T: TryGetable,
{
if let Ok(v) = T::try_get(self, col) {
Ok(Some(v))
} else {
Ok(None)
}
}
} }
// TypeErr // // TypeErr //

View File

@ -1,13 +1,13 @@
use crate::{ use crate::{
ColumnTrait, ColumnType, EntityTrait, EnumIter, Iden, Identity, IntoIdentity, ModelTrait, ColumnTrait, ColumnType, EntityTrait, EnumIter, Iden, IdenStatic, Identity, IntoIdentity,
QueryResult, Related, RelationDef, RelationTrait, Select, TypeErr, ModelTrait, QueryResult, Related, RelationDef, RelationTrait, Select, TypeErr, Value,
}; };
#[derive(Default, Debug, Iden)] #[derive(Default, Debug, Iden)]
#[iden = "cake"] #[iden = "cake"]
pub struct Entity; pub struct Entity;
#[derive(Debug, Default, PartialEq)] #[derive(Clone, Debug, Default, PartialEq)]
pub struct Model { pub struct Model {
pub id: i32, pub id: i32,
pub name: String, pub name: String,
@ -36,15 +36,42 @@ impl EntityTrait for Entity {
} }
} }
// TODO: implement with derive macro
impl ModelTrait for Model { 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<Self, TypeErr> { fn from_query_result(row: QueryResult) -> Result<Self, TypeErr> {
Ok(Self { Ok(Self {
id: row.try_get("id")?, id: row.try_get(Column::Id.as_str())?,
name: row.try_get("name")?, 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 { impl ColumnTrait for Column {
type Entity = Entity; type Entity = Entity;

View File

@ -1,13 +1,13 @@
use crate::{ use crate::{
ColumnTrait, ColumnType, EntityTrait, EnumIter, Iden, Identity, IntoIdentity, ModelTrait, ColumnTrait, ColumnType, EntityTrait, EnumIter, Iden, IdenStatic, Identity, IntoIdentity,
QueryResult, RelationDef, RelationTrait, TypeErr, ModelTrait, QueryResult, RelationDef, RelationTrait, TypeErr, Value,
}; };
#[derive(Default, Debug, Iden)] #[derive(Default, Debug, Iden)]
#[iden = "fruit"] #[iden = "fruit"]
pub struct Entity; pub struct Entity;
#[derive(Debug, Default, PartialEq)] #[derive(Clone, Debug, Default, PartialEq)]
pub struct Model { pub struct Model {
pub id: i32, pub id: i32,
pub name: String, pub name: String,
@ -36,16 +36,46 @@ impl EntityTrait for Entity {
} }
} }
// TODO: implement with derive macro
impl ModelTrait for Model { 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<Self, TypeErr> { fn from_query_result(row: QueryResult) -> Result<Self, TypeErr> {
Ok(Self { Ok(Self {
id: row.try_get("id")?, id: row.try_get(Column::Id.as_str())?,
name: row.try_get("name")?, name: row.try_get(Column::Name.as_str())?,
cake_id: row.try_get_option("cake_id")?, 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 { impl ColumnTrait for Column {
type Entity = Entity; type Entity = Entity;