Refactor JSON
This commit is contained in:
parent
92f1c012d2
commit
97e6bb3433
@ -31,11 +31,13 @@ sea-orm-macros = { path = "sea-orm-macros", optional = true }
|
|||||||
serde = { version = "^1.0", features = [ "derive" ] }
|
serde = { version = "^1.0", features = [ "derive" ] }
|
||||||
sqlx = { version = "^0.5", optional = true }
|
sqlx = { version = "^0.5", optional = true }
|
||||||
strum = { version = "^0.20", features = [ "derive" ] }
|
strum = { version = "^0.20", features = [ "derive" ] }
|
||||||
serde_json = { version = "^1.0.64", optional = true }
|
serde_json = { version = "^1", optional = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
debug-print = []
|
debug-print = []
|
||||||
default = [ "macros", "sqlx-mysql", "runtime-async-std-native-tls", "serialize-query-result" ]
|
default = [ "macros", "sqlx-mysql", "runtime-async-std-native-tls", "with-json" ]
|
||||||
|
macros = [ "sea-orm-macros" ]
|
||||||
|
with-json = [ "serde_json" ]
|
||||||
sqlx-dep = [ "sqlx" ]
|
sqlx-dep = [ "sqlx" ]
|
||||||
sqlx-mysql = [ "sqlx-dep", "sea-query/sqlx-mysql", "sqlx/mysql" ]
|
sqlx-mysql = [ "sqlx-dep", "sea-query/sqlx-mysql", "sqlx/mysql" ]
|
||||||
sqlx-postgres = [ "sqlx-dep", "sea-query/sqlx-postgres", "sqlx/postgres" ]
|
sqlx-postgres = [ "sqlx-dep", "sea-query/sqlx-postgres", "sqlx/postgres" ]
|
||||||
@ -45,5 +47,3 @@ runtime-tokio-native-tls = [ "sqlx/runtime-tokio-native-tls" ]
|
|||||||
runtime-actix-rustls = [ "sqlx/runtime-actix-rustls" ]
|
runtime-actix-rustls = [ "sqlx/runtime-actix-rustls" ]
|
||||||
runtime-async-std-rustls = [ "sqlx/runtime-async-std-rustls" ]
|
runtime-async-std-rustls = [ "sqlx/runtime-async-std-rustls" ]
|
||||||
runtime-tokio-rustls = [ "sqlx/runtime-tokio-rustls" ]
|
runtime-tokio-rustls = [ "sqlx/runtime-tokio-rustls" ]
|
||||||
macros = [ "sea-orm-macros" ]
|
|
||||||
serialize-query-result = [ "serde_json" ]
|
|
||||||
|
@ -9,4 +9,4 @@ async-std = { version = "^1.9", features = [ "attributes" ] }
|
|||||||
sea-orm = { path = "../../", features = [ "sqlx-mysql", "runtime-async-std-native-tls", "debug-print" ] }
|
sea-orm = { path = "../../", features = [ "sqlx-mysql", "runtime-async-std-native-tls", "debug-print" ] }
|
||||||
# sea-query = { path = "../../../sea-query" }
|
# sea-query = { path = "../../../sea-query" }
|
||||||
strum = { version = "^0.20", features = [ "derive" ] }
|
strum = { version = "^0.20", features = [ "derive" ] }
|
||||||
serde = { version = "^1.0", features = [ "derive" ] }
|
serde_json = { version = "^1" }
|
@ -40,21 +40,11 @@ async fn main() {
|
|||||||
|
|
||||||
find_many_to_many(&db).await.unwrap();
|
find_many_to_many(&db).await.unwrap();
|
||||||
|
|
||||||
println!("===== =====\n");
|
if false {
|
||||||
|
println!("===== =====\n");
|
||||||
|
|
||||||
find_all_json(&db).await.unwrap();
|
json_tests(&db).await.unwrap();
|
||||||
|
}
|
||||||
println!("===== =====\n");
|
|
||||||
|
|
||||||
find_one_json(&db).await.unwrap();
|
|
||||||
|
|
||||||
println!("===== =====\n");
|
|
||||||
|
|
||||||
find_together_json(&db).await.unwrap();
|
|
||||||
|
|
||||||
println!("===== =====\n");
|
|
||||||
|
|
||||||
count_fruits_by_cake_json(&db).await.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn find_all(db: &Database) -> Result<(), QueryErr> {
|
async fn find_all(db: &Database) -> Result<(), QueryErr> {
|
||||||
@ -191,38 +181,32 @@ async fn find_many_to_many(db: &Database) -> Result<(), QueryErr> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn find_all_json(db: &Database) -> Result<(), QueryErr> {
|
async fn json_tests(db: &Database) -> Result<(), QueryErr> {
|
||||||
print!("find all cakes: ");
|
find_all_json(&db).await?;
|
||||||
|
|
||||||
let cakes = cake::Entity::find().as_json().all(db).await?;
|
println!("===== =====\n");
|
||||||
|
|
||||||
println!("\n{:#?}\n", cakes);
|
find_together_json(&db).await?;
|
||||||
|
|
||||||
print!("find all fruits: ");
|
println!("===== =====\n");
|
||||||
|
|
||||||
let fruits = fruit::Entity::find().as_json().all(db).await?;
|
count_fruits_by_cake_json(&db).await?;
|
||||||
|
|
||||||
println!("\n{:#?}\n", fruits);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn find_one_json(db: &Database) -> Result<(), QueryErr> {
|
async fn find_all_json(db: &Database) -> Result<(), QueryErr> {
|
||||||
print!("find one by primary key: ");
|
print!("find all cakes: ");
|
||||||
|
|
||||||
let cheese = cake::Entity::find_by(1).as_json().one(db).await?;
|
let cakes = cake::Entity::find().into_json().all(db).await?;
|
||||||
|
|
||||||
println!("\n{:#?}\n", cheese);
|
println!("\n{}\n", serde_json::to_string_pretty(&cakes).unwrap());
|
||||||
|
|
||||||
print!("find one by like: ");
|
print!("find all fruits: ");
|
||||||
|
|
||||||
let chocolate = cake::Entity::find()
|
let fruits = fruit::Entity::find().into_json().all(db).await?;
|
||||||
.filter(cake::Column::Name.contains("chocolate"))
|
|
||||||
.as_json()
|
|
||||||
.one(db)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
println!("\n{:#?}\n", chocolate);
|
println!("\n{}\n", serde_json::to_string_pretty(&fruits).unwrap());
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -232,21 +216,24 @@ async fn find_together_json(db: &Database) -> Result<(), QueryErr> {
|
|||||||
|
|
||||||
let cakes_fruits = cake::Entity::find()
|
let cakes_fruits = cake::Entity::find()
|
||||||
.left_join_and_select(fruit::Entity)
|
.left_join_and_select(fruit::Entity)
|
||||||
.as_json()
|
.into_json()
|
||||||
.all(db)
|
.all(db)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
println!("\n{:#?}\n", cakes_fruits);
|
println!(
|
||||||
|
"\n{}\n",
|
||||||
|
serde_json::to_string_pretty(&cakes_fruits).unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
print!("find one cake and fruit: ");
|
print!("find one cake and fruit: ");
|
||||||
|
|
||||||
let cake_fruit = cake::Entity::find()
|
let cake_fruit = cake::Entity::find()
|
||||||
.left_join_and_select(fruit::Entity)
|
.left_join_and_select(fruit::Entity)
|
||||||
.as_json()
|
.into_json()
|
||||||
.one(db)
|
.one(db)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
println!("\n{:#?}\n", cake_fruit);
|
println!("\n{}\n", serde_json::to_string_pretty(&cake_fruit).unwrap());
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -260,11 +247,11 @@ async fn count_fruits_by_cake_json(db: &Database) -> Result<(), QueryErr> {
|
|||||||
.column(cake::Column::Name)
|
.column(cake::Column::Name)
|
||||||
.column_as(fruit::Column::Id.count(), "num_of_fruits")
|
.column_as(fruit::Column::Id.count(), "num_of_fruits")
|
||||||
.group_by(cake::Column::Name)
|
.group_by(cake::Column::Name)
|
||||||
.as_json()
|
.into_json()
|
||||||
.all(db)
|
.all(db)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
println!("\n{:#?}\n", count);
|
println!("\n{}\n", serde_json::to_string_pretty(&count).unwrap());
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,8 @@
|
|||||||
mod executor;
|
mod executor;
|
||||||
mod select;
|
mod select;
|
||||||
#[cfg(feature = "with-json")]
|
|
||||||
mod select_json;
|
|
||||||
|
|
||||||
pub use executor::*;
|
pub use executor::*;
|
||||||
pub use select::*;
|
pub use select::*;
|
||||||
#[cfg(feature = "with-json")]
|
|
||||||
pub use select_json::*;
|
|
||||||
|
|
||||||
use crate::{DatabaseConnection, QueryResult, Statement, TypeErr};
|
use crate::{DatabaseConnection, QueryResult, Statement, TypeErr};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
@ -5,9 +5,6 @@ use crate::{
|
|||||||
use sea_query::{QueryBuilder, SelectStatement};
|
use sea_query::{QueryBuilder, SelectStatement};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
#[cfg(feature = "with-json")]
|
|
||||||
use super::select_json::{SelectJson, SelectTwoJson};
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct SelectModel<M>
|
pub struct SelectModel<M>
|
||||||
where
|
where
|
||||||
@ -42,8 +39,11 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "with-json")]
|
#[cfg(feature = "with-json")]
|
||||||
pub fn as_json(self) -> SelectJson {
|
pub fn into_json(self) -> SelectModel<serde_json::Value> {
|
||||||
SelectJson { query: self.query }
|
SelectModel {
|
||||||
|
query: self.query,
|
||||||
|
model: PhantomData,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn one(self, db: &Database) -> Result<E::Model, QueryErr> {
|
pub async fn one(self, db: &Database) -> Result<E::Model, QueryErr> {
|
||||||
@ -72,8 +72,11 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "with-json")]
|
#[cfg(feature = "with-json")]
|
||||||
pub fn as_json(self) -> SelectTwoJson {
|
pub fn into_json(self) -> SelectTwoModel<serde_json::Value, serde_json::Value> {
|
||||||
SelectTwoJson { query: self.query }
|
SelectTwoModel {
|
||||||
|
query: self.query,
|
||||||
|
model: PhantomData,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn one(self, db: &Database) -> Result<(E::Model, F::Model), QueryErr> {
|
pub async fn one(self, db: &Database) -> Result<(E::Model, F::Model), QueryErr> {
|
||||||
|
@ -1,79 +0,0 @@
|
|||||||
use crate::query::combine;
|
|
||||||
use crate::{Connection, Database, QueryErr, Statement};
|
|
||||||
use sea_query::{QueryBuilder, SelectStatement};
|
|
||||||
use serde_json::Value as JsonValue;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct SelectJson {
|
|
||||||
pub(crate) query: SelectStatement,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SelectJson {
|
|
||||||
pub fn build<B>(&self, builder: B) -> Statement
|
|
||||||
where
|
|
||||||
B: QueryBuilder,
|
|
||||||
{
|
|
||||||
self.query.build(builder).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn one(mut self, db: &Database) -> Result<JsonValue, QueryErr> {
|
|
||||||
let builder = db.get_query_builder_backend();
|
|
||||||
self.query.limit(1);
|
|
||||||
// TODO: Error handling
|
|
||||||
db.get_connection()
|
|
||||||
.query_one(self.build(builder))
|
|
||||||
.await?
|
|
||||||
.as_json("")
|
|
||||||
.map_err(|_e| QueryErr)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn all(self, db: &Database) -> Result<JsonValue, QueryErr> {
|
|
||||||
let builder = db.get_query_builder_backend();
|
|
||||||
let rows = db.get_connection().query_all(self.build(builder)).await?;
|
|
||||||
let mut values = Vec::new();
|
|
||||||
for row in rows.into_iter() {
|
|
||||||
// TODO: Error handling
|
|
||||||
values.push(row.as_json("").map_err(|_e| QueryErr)?);
|
|
||||||
}
|
|
||||||
Ok(JsonValue::Array(values))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct SelectTwoJson {
|
|
||||||
pub(crate) query: SelectStatement,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SelectTwoJson {
|
|
||||||
pub fn build<B>(&self, builder: B) -> Statement
|
|
||||||
where
|
|
||||||
B: QueryBuilder,
|
|
||||||
{
|
|
||||||
self.query.build(builder).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn one(mut self, db: &Database) -> Result<JsonValue, QueryErr> {
|
|
||||||
let builder = db.get_query_builder_backend();
|
|
||||||
self.query.limit(1);
|
|
||||||
let row = db.get_connection().query_one(self.build(builder)).await?;
|
|
||||||
Ok(JsonValue::Array(vec![
|
|
||||||
// TODO: Error handling
|
|
||||||
row.as_json(combine::SELECT_A).map_err(|_e| QueryErr)?,
|
|
||||||
row.as_json(combine::SELECT_B).map_err(|_e| QueryErr)?,
|
|
||||||
]))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn all(self, db: &Database) -> Result<JsonValue, QueryErr> {
|
|
||||||
let builder = db.get_query_builder_backend();
|
|
||||||
let rows = db.get_connection().query_all(self.build(builder)).await?;
|
|
||||||
let mut json_values = Vec::new();
|
|
||||||
for row in rows.into_iter() {
|
|
||||||
json_values.push(JsonValue::Array(vec![
|
|
||||||
// TODO: Error handling
|
|
||||||
row.as_json(combine::SELECT_A).map_err(|_e| QueryErr)?,
|
|
||||||
row.as_json(combine::SELECT_B).map_err(|_e| QueryErr)?,
|
|
||||||
]));
|
|
||||||
}
|
|
||||||
Ok(JsonValue::Array(json_values))
|
|
||||||
}
|
|
||||||
}
|
|
@ -9,13 +9,13 @@ pub trait ModelTrait: Clone + Debug {
|
|||||||
|
|
||||||
fn set(&mut self, c: Self::Column, v: Value);
|
fn set(&mut self, c: Self::Column, v: Value);
|
||||||
|
|
||||||
fn from_query_result(row: &QueryResult, pre: &str) -> Result<Self, TypeErr>
|
fn from_query_result(res: &QueryResult, pre: &str) -> Result<Self, TypeErr>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait FromQueryResult {
|
pub trait FromQueryResult {
|
||||||
fn from_query_result(row: &QueryResult, pre: &str) -> Result<Self, TypeErr>
|
fn from_query_result(res: &QueryResult, pre: &str) -> Result<Self, TypeErr>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
}
|
}
|
||||||
@ -24,7 +24,7 @@ impl<M> FromQueryResult for M
|
|||||||
where
|
where
|
||||||
M: ModelTrait + Sized,
|
M: ModelTrait + Sized,
|
||||||
{
|
{
|
||||||
fn from_query_result(row: &QueryResult, pre: &str) -> Result<M, TypeErr> {
|
fn from_query_result(res: &QueryResult, pre: &str) -> Result<M, TypeErr> {
|
||||||
<Self as ModelTrait>::from_query_result(row, pre)
|
<Self as ModelTrait>::from_query_result(res, pre)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
42
src/query/json.rs
Normal file
42
src/query/json.rs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
use crate::{FromQueryResult, QueryResult, QueryResultRow, TypeErr};
|
||||||
|
use serde_json::{json, Map, Value};
|
||||||
|
|
||||||
|
impl FromQueryResult for Value {
|
||||||
|
fn from_query_result(res: &QueryResult, pre: &str) -> Result<Self, TypeErr> {
|
||||||
|
match &res.row {
|
||||||
|
QueryResultRow::SqlxMySql(row) => {
|
||||||
|
use sqlx::{Column, MySql, Row, Type};
|
||||||
|
let mut map = Map::new();
|
||||||
|
for column in row.columns() {
|
||||||
|
let col = if !column.name().starts_with(pre) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
column.name().replacen(pre, "", 1)
|
||||||
|
};
|
||||||
|
let col_type = column.type_info();
|
||||||
|
macro_rules! match_mysql_type {
|
||||||
|
( $type: ty ) => {
|
||||||
|
if <$type as Type<MySql>>::type_info().eq(col_type) {
|
||||||
|
map.insert(col.to_owned(), json!(res.try_get::<$type>(pre, &col)?));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
match_mysql_type!(bool);
|
||||||
|
match_mysql_type!(i8);
|
||||||
|
match_mysql_type!(i16);
|
||||||
|
match_mysql_type!(i32);
|
||||||
|
match_mysql_type!(i64);
|
||||||
|
match_mysql_type!(u8);
|
||||||
|
match_mysql_type!(u16);
|
||||||
|
match_mysql_type!(u32);
|
||||||
|
match_mysql_type!(u64);
|
||||||
|
match_mysql_type!(f32);
|
||||||
|
match_mysql_type!(f64);
|
||||||
|
match_mysql_type!(String);
|
||||||
|
}
|
||||||
|
Ok(Value::Object(map))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,15 @@
|
|||||||
pub(crate) mod combine;
|
pub(crate) mod combine;
|
||||||
mod helper;
|
mod helper;
|
||||||
mod join;
|
mod join;
|
||||||
|
#[cfg(feature = "with-json")]
|
||||||
|
mod json;
|
||||||
mod result;
|
mod result;
|
||||||
mod select;
|
mod select;
|
||||||
|
|
||||||
pub use combine::*;
|
pub use combine::*;
|
||||||
pub use helper::*;
|
pub use helper::*;
|
||||||
pub use join::*;
|
pub use join::*;
|
||||||
|
#[cfg(feature = "with-json")]
|
||||||
|
pub use json::*;
|
||||||
pub use result::*;
|
pub use result::*;
|
||||||
pub use select::*;
|
pub use select::*;
|
||||||
|
@ -75,49 +75,6 @@ impl QueryResult {
|
|||||||
{
|
{
|
||||||
T::try_get(self, pre, col)
|
T::try_get(self, pre, col)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "with-json")]
|
|
||||||
pub fn as_json(&self, pre: &str) -> Result<serde_json::Value, TypeErr> {
|
|
||||||
use serde_json::{json, Map, Value};
|
|
||||||
match &self.row {
|
|
||||||
QueryResultRow::SqlxMySql(row) => {
|
|
||||||
use sqlx::{Column, MySql, Row, Type};
|
|
||||||
let mut map = Map::new();
|
|
||||||
for column in row.columns() {
|
|
||||||
let col = if !column.name().starts_with(pre) {
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
column.name().replacen(pre, "", 1)
|
|
||||||
};
|
|
||||||
let col_type = column.type_info();
|
|
||||||
macro_rules! match_mysql_type {
|
|
||||||
( $type: ty ) => {
|
|
||||||
if <$type as Type<MySql>>::type_info().eq(col_type) {
|
|
||||||
map.insert(
|
|
||||||
col.to_owned(),
|
|
||||||
json!(self.try_get::<$type>(pre, &col)?),
|
|
||||||
);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
match_mysql_type!(bool);
|
|
||||||
match_mysql_type!(i8);
|
|
||||||
match_mysql_type!(i16);
|
|
||||||
match_mysql_type!(i32);
|
|
||||||
match_mysql_type!(i64);
|
|
||||||
match_mysql_type!(u8);
|
|
||||||
match_mysql_type!(u16);
|
|
||||||
match_mysql_type!(u32);
|
|
||||||
match_mysql_type!(u64);
|
|
||||||
match_mysql_type!(f32);
|
|
||||||
match_mysql_type!(f64);
|
|
||||||
match_mysql_type!(String);
|
|
||||||
}
|
|
||||||
Ok(Value::Object(map))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TypeErr //
|
// TypeErr //
|
||||||
|
Loading…
x
Reference in New Issue
Block a user