QueryResult to Model

This commit is contained in:
Chris Tsang 2021-05-07 21:22:19 +08:00
parent 98b0e9df95
commit 59b747bf55
9 changed files with 110 additions and 16 deletions

View File

@ -0,0 +1,15 @@
# SeaORM SQLx MySql example
Running:
```sh
cargo run
```
Example output:
```sh
Database { connection: SqlxMySqlPoolConnection }
CakeModel { id: 1, name: "New York Cheese" }
CakeModel { id: 2, name: "Chocolate Fudge" }
```

View File

@ -7,12 +7,12 @@ async fn main() {
.await
.unwrap();
println!("{:?}", db);
println!("");
println!();
let rows = cake::Cake::find().all(&db).await.unwrap();
let cakes = cake::Cake::find().all(&db).await.unwrap();
for row in rows.iter() {
println!("{:?}", row);
println!("");
for cc in cakes.iter() {
println!("{:?}", cc);
println!();
}
}

View File

@ -2,7 +2,7 @@ mod select;
pub use select::*;
use crate::{DatabaseConnection, QueryResult};
use crate::{DatabaseConnection, QueryResult, TypeErr};
use async_trait::async_trait;
use sea_query::{inject_parameters, MySqlQueryBuilder, Values};
use std::{error::Error, fmt};
@ -64,6 +64,12 @@ impl fmt::Display for QueryErr {
}
}
impl From<TypeErr> for QueryErr {
fn from(_: TypeErr) -> QueryErr {
QueryErr
}
}
// ConnectionErr //
impl Error for ConnectionErr {}

View File

@ -1,16 +1,22 @@
use crate::{Connection, Database, Entity, QueryErr, QueryResult, Select};
use crate::{Connection, Database, Entity, Model, QueryErr, Select};
impl<E: 'static> Select<'_, E>
where
E: Entity,
{
pub async fn one(self, db: &Database) -> Result<QueryResult, QueryErr> {
pub async fn one(self, db: &Database) -> Result<E::Model, QueryErr> {
let builder = db.get_query_builder_backend();
db.get_connection().query_one(self.build(builder)).await
let row = db.get_connection().query_one(self.build(builder)).await?;
Ok(<E as Entity>::Model::from_query_result(row)?)
}
pub async fn all(self, db: &Database) -> Result<Vec<QueryResult>, QueryErr> {
pub async fn all(self, db: &Database) -> Result<Vec<E::Model>, QueryErr> {
let builder = db.get_query_builder_backend();
db.get_connection().query_all(self.build(builder)).await
let rows = db.get_connection().query_all(self.build(builder)).await?;
let mut models = Vec::new();
for row in rows.into_iter() {
models.push(<E as Entity>::Model::from_query_result(row)?);
}
Ok(models)
}
}

View File

@ -1,11 +1,11 @@
use super::{Column, Identity, Relation};
use super::{Column, Identity, Model, Relation};
use crate::Select;
use sea_query::Iden;
use std::fmt::Debug;
use strum::IntoEnumIterator;
pub trait Entity: Iden + Default + Debug {
type Model;
type Model: Model;
type Column: Column + IntoEnumIterator;

View File

@ -1,9 +1,11 @@
mod base;
mod column;
mod identity;
mod model;
mod relation;
pub use base::*;
pub use column::*;
pub use identity::*;
pub use model::*;
pub use relation::*;

7
src/entity/model.rs Normal file
View File

@ -0,0 +1,7 @@
use crate::{QueryResult, TypeErr};
pub trait Model {
fn from_query_result(row: QueryResult) -> Result<Self, TypeErr>
where
Self: std::marker::Sized;
}

View File

@ -1,4 +1,5 @@
use sqlx::mysql::MySqlRow;
use std::{error::Error, fmt};
#[derive(Debug)]
pub struct QueryResult {
@ -9,3 +10,48 @@ pub struct QueryResult {
pub(crate) enum QueryResultRow {
SqlxMySql(MySqlRow),
}
#[derive(Debug)]
pub struct TypeErr;
// QueryResult //
impl QueryResult {
pub fn try_get_i32(&self, col: &str) -> Result<i32, TypeErr> {
match &self.row {
QueryResultRow::SqlxMySql(row) => {
use sqlx::Row;
if let Ok(val) = row.try_get(col) {
Ok(val)
} else {
Err(TypeErr)
}
}
}
}
pub fn try_get_string(&self, col: &str) -> Result<String, TypeErr> {
match &self.row {
QueryResultRow::SqlxMySql(row) => {
use sqlx::Row;
if let Ok(val) = row.try_get(col) {
Ok(val)
} else {
Err(TypeErr)
}
}
}
}
}
// TypeErr //
impl Error for TypeErr {}
impl fmt::Display for TypeErr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self)
}
}

View File

@ -1,4 +1,7 @@
use crate::{Column, ColumnType, Entity, Identity, IntoIdentity, Relation, RelationDef};
use crate::{
Column, ColumnType, Entity, Identity, IntoIdentity, Model, QueryResult, Relation, RelationDef,
TypeErr,
};
use sea_query::Iden;
use strum::EnumIter;
@ -7,8 +10,8 @@ pub struct Cake;
#[derive(Debug, Default, PartialEq)]
pub struct CakeModel {
pub id: Option<i32>,
pub name: Option<String>,
pub id: i32,
pub name: String,
}
#[derive(Iden, EnumIter)]
@ -46,3 +49,12 @@ impl Relation for CakeRelation {
panic!()
}
}
impl Model for CakeModel {
fn from_query_result(row: QueryResult) -> Result<Self, TypeErr> {
Ok(Self {
id: row.try_get_i32("id")?,
name: row.try_get_string("name")?,
})
}
}