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
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
println!("{:?}", db);
|
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() {
|
for cc in cakes.iter() {
|
||||||
println!("{:?}", row);
|
println!("{:?}", cc);
|
||||||
println!("");
|
println!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ mod select;
|
|||||||
|
|
||||||
pub use select::*;
|
pub use select::*;
|
||||||
|
|
||||||
use crate::{DatabaseConnection, QueryResult};
|
use crate::{DatabaseConnection, QueryResult, TypeErr};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use sea_query::{inject_parameters, MySqlQueryBuilder, Values};
|
use sea_query::{inject_parameters, MySqlQueryBuilder, Values};
|
||||||
use std::{error::Error, fmt};
|
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 //
|
// ConnectionErr //
|
||||||
|
|
||||||
impl Error for 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>
|
impl<E: 'static> Select<'_, E>
|
||||||
where
|
where
|
||||||
E: Entity,
|
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();
|
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();
|
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 crate::Select;
|
||||||
use sea_query::Iden;
|
use sea_query::Iden;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
pub trait Entity: Iden + Default + Debug {
|
pub trait Entity: Iden + Default + Debug {
|
||||||
type Model;
|
type Model: Model;
|
||||||
|
|
||||||
type Column: Column + IntoEnumIterator;
|
type Column: Column + IntoEnumIterator;
|
||||||
|
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
mod base;
|
mod base;
|
||||||
mod column;
|
mod column;
|
||||||
mod identity;
|
mod identity;
|
||||||
|
mod model;
|
||||||
mod relation;
|
mod relation;
|
||||||
|
|
||||||
pub use base::*;
|
pub use base::*;
|
||||||
pub use column::*;
|
pub use column::*;
|
||||||
pub use identity::*;
|
pub use identity::*;
|
||||||
|
pub use model::*;
|
||||||
pub use relation::*;
|
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 sqlx::mysql::MySqlRow;
|
||||||
|
use std::{error::Error, fmt};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct QueryResult {
|
pub struct QueryResult {
|
||||||
@ -9,3 +10,48 @@ pub struct QueryResult {
|
|||||||
pub(crate) enum QueryResultRow {
|
pub(crate) enum QueryResultRow {
|
||||||
SqlxMySql(MySqlRow),
|
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 sea_query::Iden;
|
||||||
use strum::EnumIter;
|
use strum::EnumIter;
|
||||||
|
|
||||||
@ -7,8 +10,8 @@ pub struct Cake;
|
|||||||
|
|
||||||
#[derive(Debug, Default, PartialEq)]
|
#[derive(Debug, Default, PartialEq)]
|
||||||
pub struct CakeModel {
|
pub struct CakeModel {
|
||||||
pub id: Option<i32>,
|
pub id: i32,
|
||||||
pub name: Option<String>,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Iden, EnumIter)]
|
#[derive(Iden, EnumIter)]
|
||||||
@ -46,3 +49,12 @@ impl Relation for CakeRelation {
|
|||||||
panic!()
|
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