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;
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>
where
Self: std::marker::Sized;

View File

@ -17,32 +17,52 @@ pub struct TypeErr;
pub trait TryGetable {
fn try_get(res: &QueryResult, col: &str) -> Result<Self, TypeErr>
where
Self: std::marker::Sized;
Self: Sized;
}
// TryGetable //
impl TryGetable for i32 {
fn try_get(res: &QueryResult, col: &str) -> Result<Self, TypeErr> {
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<Self, TypeErr> {
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<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 {
fn try_get(res: &QueryResult, col: &str) -> Result<Self, TypeErr> {
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<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 //

View File

@ -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<Self, TypeErr> {
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;

View File

@ -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<Self, TypeErr> {
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;