From 97e6bb34335514428038f86bb3449dc58fac6ba9 Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Thu, 27 May 2021 03:45:00 +0800 Subject: [PATCH] Refactor JSON --- Cargo.toml | 10 ++--- examples/sqlx-mysql/Cargo.toml | 2 +- examples/sqlx-mysql/src/main.rs | 65 +++++++++++---------------- src/connector/mod.rs | 4 -- src/connector/select.rs | 17 ++++--- src/connector/select_json.rs | 79 --------------------------------- src/entity/model.rs | 8 ++-- src/query/json.rs | 42 ++++++++++++++++++ src/query/mod.rs | 4 ++ src/query/result.rs | 43 ------------------ 10 files changed, 92 insertions(+), 182 deletions(-) delete mode 100644 src/connector/select_json.rs create mode 100644 src/query/json.rs diff --git a/Cargo.toml b/Cargo.toml index 11d0d7eb..7b820837 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,11 +31,13 @@ sea-orm-macros = { path = "sea-orm-macros", optional = true } serde = { version = "^1.0", features = [ "derive" ] } sqlx = { version = "^0.5", optional = true } strum = { version = "^0.20", features = [ "derive" ] } -serde_json = { version = "^1.0.64", optional = true } +serde_json = { version = "^1", optional = true } [features] 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-mysql = [ "sqlx-dep", "sea-query/sqlx-mysql", "sqlx/mysql" ] sqlx-postgres = [ "sqlx-dep", "sea-query/sqlx-postgres", "sqlx/postgres" ] @@ -44,6 +46,4 @@ runtime-async-std-native-tls = [ "sqlx/runtime-async-std-native-tls" ] runtime-tokio-native-tls = [ "sqlx/runtime-tokio-native-tls" ] runtime-actix-rustls = [ "sqlx/runtime-actix-rustls" ] runtime-async-std-rustls = [ "sqlx/runtime-async-std-rustls" ] -runtime-tokio-rustls = [ "sqlx/runtime-tokio-rustls" ] -macros = [ "sea-orm-macros" ] -serialize-query-result = [ "serde_json" ] +runtime-tokio-rustls = [ "sqlx/runtime-tokio-rustls" ] \ No newline at end of file diff --git a/examples/sqlx-mysql/Cargo.toml b/examples/sqlx-mysql/Cargo.toml index ed22ec9d..3bb96883 100644 --- a/examples/sqlx-mysql/Cargo.toml +++ b/examples/sqlx-mysql/Cargo.toml @@ -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-query = { path = "../../../sea-query" } strum = { version = "^0.20", features = [ "derive" ] } -serde = { version = "^1.0", features = [ "derive" ] } \ No newline at end of file +serde_json = { version = "^1" } \ No newline at end of file diff --git a/examples/sqlx-mysql/src/main.rs b/examples/sqlx-mysql/src/main.rs index d21af5da..7133e795 100644 --- a/examples/sqlx-mysql/src/main.rs +++ b/examples/sqlx-mysql/src/main.rs @@ -40,21 +40,11 @@ async fn main() { find_many_to_many(&db).await.unwrap(); - println!("===== =====\n"); + if false { + println!("===== =====\n"); - find_all_json(&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(); + json_tests(&db).await.unwrap(); + } } async fn find_all(db: &Database) -> Result<(), QueryErr> { @@ -191,38 +181,32 @@ async fn find_many_to_many(db: &Database) -> Result<(), QueryErr> { Ok(()) } -async fn find_all_json(db: &Database) -> Result<(), QueryErr> { - print!("find all cakes: "); +async fn json_tests(db: &Database) -> Result<(), QueryErr> { + 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?; - - println!("\n{:#?}\n", fruits); + count_fruits_by_cake_json(&db).await?; Ok(()) } -async fn find_one_json(db: &Database) -> Result<(), QueryErr> { - print!("find one by primary key: "); +async fn find_all_json(db: &Database) -> Result<(), QueryErr> { + 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() - .filter(cake::Column::Name.contains("chocolate")) - .as_json() - .one(db) - .await?; + let fruits = fruit::Entity::find().into_json().all(db).await?; - println!("\n{:#?}\n", chocolate); + println!("\n{}\n", serde_json::to_string_pretty(&fruits).unwrap()); Ok(()) } @@ -232,21 +216,24 @@ async fn find_together_json(db: &Database) -> Result<(), QueryErr> { let cakes_fruits = cake::Entity::find() .left_join_and_select(fruit::Entity) - .as_json() + .into_json() .all(db) .await?; - println!("\n{:#?}\n", cakes_fruits); + println!( + "\n{}\n", + serde_json::to_string_pretty(&cakes_fruits).unwrap() + ); print!("find one cake and fruit: "); let cake_fruit = cake::Entity::find() .left_join_and_select(fruit::Entity) - .as_json() + .into_json() .one(db) .await?; - println!("\n{:#?}\n", cake_fruit); + println!("\n{}\n", serde_json::to_string_pretty(&cake_fruit).unwrap()); Ok(()) } @@ -260,11 +247,11 @@ async fn count_fruits_by_cake_json(db: &Database) -> Result<(), QueryErr> { .column(cake::Column::Name) .column_as(fruit::Column::Id.count(), "num_of_fruits") .group_by(cake::Column::Name) - .as_json() + .into_json() .all(db) .await?; - println!("\n{:#?}\n", count); + println!("\n{}\n", serde_json::to_string_pretty(&count).unwrap()); Ok(()) } diff --git a/src/connector/mod.rs b/src/connector/mod.rs index c05a9630..bb1585d8 100644 --- a/src/connector/mod.rs +++ b/src/connector/mod.rs @@ -1,12 +1,8 @@ mod executor; mod select; -#[cfg(feature = "with-json")] -mod select_json; pub use executor::*; pub use select::*; -#[cfg(feature = "with-json")] -pub use select_json::*; use crate::{DatabaseConnection, QueryResult, Statement, TypeErr}; use async_trait::async_trait; diff --git a/src/connector/select.rs b/src/connector/select.rs index f3192f51..4db557de 100644 --- a/src/connector/select.rs +++ b/src/connector/select.rs @@ -5,9 +5,6 @@ use crate::{ use sea_query::{QueryBuilder, SelectStatement}; use std::marker::PhantomData; -#[cfg(feature = "with-json")] -use super::select_json::{SelectJson, SelectTwoJson}; - #[derive(Clone, Debug)] pub struct SelectModel where @@ -42,8 +39,11 @@ where } #[cfg(feature = "with-json")] - pub fn as_json(self) -> SelectJson { - SelectJson { query: self.query } + pub fn into_json(self) -> SelectModel { + SelectModel { + query: self.query, + model: PhantomData, + } } pub async fn one(self, db: &Database) -> Result { @@ -72,8 +72,11 @@ where } #[cfg(feature = "with-json")] - pub fn as_json(self) -> SelectTwoJson { - SelectTwoJson { query: self.query } + pub fn into_json(self) -> SelectTwoModel { + SelectTwoModel { + query: self.query, + model: PhantomData, + } } pub async fn one(self, db: &Database) -> Result<(E::Model, F::Model), QueryErr> { diff --git a/src/connector/select_json.rs b/src/connector/select_json.rs deleted file mode 100644 index 0a061231..00000000 --- a/src/connector/select_json.rs +++ /dev/null @@ -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(&self, builder: B) -> Statement - where - B: QueryBuilder, - { - self.query.build(builder).into() - } - - pub async fn one(mut self, db: &Database) -> Result { - 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 { - 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(&self, builder: B) -> Statement - where - B: QueryBuilder, - { - self.query.build(builder).into() - } - - pub async fn one(mut self, db: &Database) -> Result { - 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 { - 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)) - } -} diff --git a/src/entity/model.rs b/src/entity/model.rs index 4d3dd625..eba9761a 100644 --- a/src/entity/model.rs +++ b/src/entity/model.rs @@ -9,13 +9,13 @@ pub trait ModelTrait: Clone + Debug { fn set(&mut self, c: Self::Column, v: Value); - fn from_query_result(row: &QueryResult, pre: &str) -> Result + fn from_query_result(res: &QueryResult, pre: &str) -> Result where Self: Sized; } pub trait FromQueryResult { - fn from_query_result(row: &QueryResult, pre: &str) -> Result + fn from_query_result(res: &QueryResult, pre: &str) -> Result where Self: Sized; } @@ -24,7 +24,7 @@ impl FromQueryResult for M where M: ModelTrait + Sized, { - fn from_query_result(row: &QueryResult, pre: &str) -> Result { - ::from_query_result(row, pre) + fn from_query_result(res: &QueryResult, pre: &str) -> Result { + ::from_query_result(res, pre) } } diff --git a/src/query/json.rs b/src/query/json.rs new file mode 100644 index 00000000..864ff93d --- /dev/null +++ b/src/query/json.rs @@ -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 { + 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>::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)) + } + } + } +} diff --git a/src/query/mod.rs b/src/query/mod.rs index 27bebe51..c894f4bf 100644 --- a/src/query/mod.rs +++ b/src/query/mod.rs @@ -1,11 +1,15 @@ pub(crate) mod combine; mod helper; mod join; +#[cfg(feature = "with-json")] +mod json; mod result; mod select; pub use combine::*; pub use helper::*; pub use join::*; +#[cfg(feature = "with-json")] +pub use json::*; pub use result::*; pub use select::*; diff --git a/src/query/result.rs b/src/query/result.rs index 4df8c1f3..713fbb87 100644 --- a/src/query/result.rs +++ b/src/query/result.rs @@ -75,49 +75,6 @@ impl QueryResult { { T::try_get(self, pre, col) } - - #[cfg(feature = "with-json")] - pub fn as_json(&self, pre: &str) -> Result { - 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>::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 //