From 486a081509e23a65d5a11d10f9e60fc5471d4c8a Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Sun, 9 May 2021 21:10:57 +0800 Subject: [PATCH] Improve API --- examples/bakery.sql | 11 +++++- examples/sqlx-mysql/src/example_cake.rs | 2 +- examples/sqlx-mysql/src/example_fruit.rs | 3 +- examples/sqlx-mysql/src/main.rs | 16 ++++++--- src/connector/select.rs | 3 +- src/entity/base.rs | 46 ++++++++++++------------ src/entity/column.rs | 22 ++++++++++++ src/entity/relation.rs | 1 - src/query/select.rs | 2 +- src/tests_cfg/cake.rs | 2 +- src/tests_cfg/fruit.rs | 3 +- 11 files changed, 73 insertions(+), 38 deletions(-) diff --git a/examples/bakery.sql b/examples/bakery.sql index 54206992..4a811238 100644 --- a/examples/bakery.sql +++ b/examples/bakery.sql @@ -6,11 +6,20 @@ CREATE TABLE `cake` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; +INSERT INTO `cake` (`id`, `name`) VALUES + (1, 'New York Cheese'), + (2, 'Chocolate Fudge'); + DROP TABLE IF EXISTS `fruit`; CREATE TABLE `fruit` ( `id` int NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, - `cake_id` int, + `cake_id` int DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +INSERT INTO `fruit` (`id`, `name`, `cake_id`) VALUES + (1, 'Blueberry', 1), + (2, 'Rasberry', 1), + (3, 'Strawberry', 2); \ No newline at end of file diff --git a/examples/sqlx-mysql/src/example_cake.rs b/examples/sqlx-mysql/src/example_cake.rs index 0f3e92a0..3a821203 100644 --- a/examples/sqlx-mysql/src/example_cake.rs +++ b/examples/sqlx-mysql/src/example_cake.rs @@ -155,4 +155,4 @@ impl PrimaryKeyOfModel for PrimaryKey { Self::Id => Column::Id, } } -} \ No newline at end of file +} diff --git a/examples/sqlx-mysql/src/example_fruit.rs b/examples/sqlx-mysql/src/example_fruit.rs index d41ea685..3f624f7f 100644 --- a/examples/sqlx-mysql/src/example_fruit.rs +++ b/examples/sqlx-mysql/src/example_fruit.rs @@ -117,7 +117,6 @@ impl IdenStatic for Column { } } - // TODO: implement with derive macro impl Iden for PrimaryKey { fn unquoted(&self, s: &mut dyn std::fmt::Write) { @@ -144,4 +143,4 @@ impl PrimaryKeyOfModel for PrimaryKey { Self::Id => Column::Id, } } -} \ No newline at end of file +} diff --git a/examples/sqlx-mysql/src/main.rs b/examples/sqlx-mysql/src/main.rs index f817aacb..e1dc88f6 100644 --- a/examples/sqlx-mysql/src/main.rs +++ b/examples/sqlx-mysql/src/main.rs @@ -15,7 +15,7 @@ async fn main() { println!("{:?}", db); println!(); - println!("find all"); + print!("find all: "); let cakes = cake::Entity::find().all(&db).await.unwrap(); @@ -25,15 +25,23 @@ async fn main() { println!(); } - println!("find one by primary key"); + let fruits = fruit::Entity::find().all(&db).await.unwrap(); - let cheese = cake::Entity::find_one(&db, 1).await.unwrap(); + println!(); + for cc in fruits.iter() { + println!("{:?}", cc); + println!(); + } + + print!("find one by primary key: "); + + let cheese = cake::Entity::find_by(1).one(&db).await.unwrap(); println!(); println!("{:?}", cheese); println!(); - println!("find models belongs to"); + print!("find models belong to: "); let fruits = cheese.find_fruit().all(&db).await.unwrap(); diff --git a/src/connector/select.rs b/src/connector/select.rs index 07a4daa8..e3ea6fb3 100644 --- a/src/connector/select.rs +++ b/src/connector/select.rs @@ -4,8 +4,9 @@ impl Select where E: EntityTrait, { - pub async fn one(self, db: &Database) -> Result { + 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(::Model::from_query_result(row)?) } diff --git a/src/entity/base.rs b/src/entity/base.rs index a5db1611..ab179d1f 100644 --- a/src/entity/base.rs +++ b/src/entity/base.rs @@ -1,6 +1,5 @@ use crate::{ - ColumnTrait, Connection, Database, ModelTrait, PrimaryKeyTrait, QueryErr, RelationBuilder, - RelationTrait, RelationType, Select, + ColumnTrait, ModelTrait, PrimaryKeyTrait, RelationBuilder, RelationTrait, RelationType, Select, }; use async_trait::async_trait; use sea_query::{Expr, Iden, IntoIden, Value}; @@ -41,13 +40,6 @@ pub trait EntityTrait: EntityName { RelationBuilder::new(RelationType::HasMany, Self::default(), entity) } - fn belongs_to(entity: E) -> RelationBuilder - where - E: IntoIden, - { - RelationBuilder::new(RelationType::BelongsTo, Self::default(), entity) - } - /// ``` /// use sea_orm::{ColumnTrait, EntityTrait, tests_cfg::cake, sea_query::MysqlQueryBuilder}; /// @@ -62,22 +54,28 @@ pub trait EntityTrait: EntityName { Select::::new() } - async fn find_one(db: &Database, v: V) -> Result + /// Find a model by primary key + /// ``` + /// use sea_orm::{ColumnTrait, EntityTrait, tests_cfg::cake, sea_query::MysqlQueryBuilder}; + /// + /// assert_eq!( + /// cake::Entity::find_by(11) + /// .build(MysqlQueryBuilder) + /// .to_string(), + /// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`id` = 11" + /// ); + /// ``` + fn find_by(v: V) -> Select where - V: Into + Send, + V: Into, { - let builder = db.get_query_builder_backend(); - let stmt = { - let mut select = Self::find(); - if let Some(key) = Self::PrimaryKey::iter().next() { - // TODO: supporting composite primary key - select = select.filter(Expr::tbl(Self::default(), key).eq(v)); - } else { - panic!("undefined primary key"); - } - select.build(builder) - }; - let row = db.get_connection().query_one(stmt).await?; - Ok(Self::Model::from_query_result(row)?) + let mut select = Self::find(); + if let Some(key) = Self::PrimaryKey::iter().next() { + // TODO: supporting composite primary key + select = select.filter(Expr::tbl(Self::default(), key).eq(v)); + } else { + panic!("undefined primary key"); + } + select } } diff --git a/src/entity/column.rs b/src/entity/column.rs index 5d38befc..82c09f92 100644 --- a/src/entity/column.rs +++ b/src/entity/column.rs @@ -31,6 +31,17 @@ pub trait ColumnTrait: IdenStatic { bind_oper!(lt); bind_oper!(lte); + /// ``` + /// use sea_orm::{ColumnTrait, EntityTrait, tests_cfg::cake, sea_query::MysqlQueryBuilder}; + /// + /// assert_eq!( + /// cake::Entity::find() + /// .filter(cake::Column::Id.between(2,3)) + /// .build(MysqlQueryBuilder) + /// .to_string(), + /// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`id` BETWEEN 2 AND 3" + /// ); + /// ``` fn between(&self, a: V, b: V) -> SimpleExpr where V: Into, @@ -38,6 +49,17 @@ pub trait ColumnTrait: IdenStatic { Expr::tbl(self.as_iden(), *self).between(a, b) } + /// ``` + /// use sea_orm::{ColumnTrait, EntityTrait, tests_cfg::cake, sea_query::MysqlQueryBuilder}; + /// + /// assert_eq!( + /// cake::Entity::find() + /// .filter(cake::Column::Id.not_between(2,3)) + /// .build(MysqlQueryBuilder) + /// .to_string(), + /// "SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`id` NOT BETWEEN 2 AND 3" + /// ); + /// ``` fn not_between(&self, a: V, b: V) -> SimpleExpr where V: Into, diff --git a/src/entity/relation.rs b/src/entity/relation.rs index 0a8b7bd8..15629f80 100644 --- a/src/entity/relation.rs +++ b/src/entity/relation.rs @@ -7,7 +7,6 @@ use std::rc::Rc; pub enum RelationType { HasOne, HasMany, - BelongsTo, } pub trait RelationTrait: Debug + 'static { diff --git a/src/query/select.rs b/src/query/select.rs index 70870109..039df62b 100644 --- a/src/query/select.rs +++ b/src/query/select.rs @@ -8,7 +8,7 @@ pub use sea_query::JoinType; use sea_query::{Expr, Iden, IntoIden, Order, QueryBuilder, SelectStatement, SimpleExpr}; use std::rc::Rc; -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct Select where E: EntityTrait, diff --git a/src/tests_cfg/cake.rs b/src/tests_cfg/cake.rs index 99174199..d36c4e8a 100644 --- a/src/tests_cfg/cake.rs +++ b/src/tests_cfg/cake.rs @@ -155,4 +155,4 @@ impl PrimaryKeyOfModel for PrimaryKey { Self::Id => Column::Id, } } -} \ No newline at end of file +} diff --git a/src/tests_cfg/fruit.rs b/src/tests_cfg/fruit.rs index e29b6f58..1aa8d21f 100644 --- a/src/tests_cfg/fruit.rs +++ b/src/tests_cfg/fruit.rs @@ -117,7 +117,6 @@ impl IdenStatic for Column { } } - // TODO: implement with derive macro impl Iden for PrimaryKey { fn unquoted(&self, s: &mut dyn std::fmt::Write) { @@ -144,4 +143,4 @@ impl PrimaryKeyOfModel for PrimaryKey { Self::Id => Column::Id, } } -} \ No newline at end of file +}