QueryResult to Model
This commit is contained in:
parent
98b0e9df95
commit
59b747bf55
15
examples/sqlx-mysql/Readme.md
Normal file
15
examples/sqlx-mysql/Readme.md
Normal 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" }
|
||||
```
|
@ -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!();
|
||||
}
|
||||
}
|
||||
|
@ -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 {}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
7
src/entity/model.rs
Normal 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;
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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")?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user