Update README & lib.rs
This commit is contained in:
parent
cb60c4afa3
commit
c9047d49e7
107
README.md
107
README.md
@ -31,18 +31,125 @@ SeaORM is a relational ORM to help you build light weight and concurrent web ser
|
||||
|
||||
Relying on [SQLx](https://github.com/launchbadge/sqlx), SeaORM is a new library with async support from day 1.
|
||||
|
||||
```rust
|
||||
// execute multiple queries in parallel
|
||||
let cakes_and_fruits: (Vec<cake::Model>, Vec<fruit::Model>) =
|
||||
futures::try_join!(Cake::find().all(&db), Fruit::find().all(&db))?;
|
||||
|
||||
```
|
||||
|
||||
2. Dynamic
|
||||
|
||||
Built upon [SeaQuery](https://github.com/SeaQL/sea-query), SeaORM allows you to build complex queries without 'fighting the ORM'.
|
||||
|
||||
```rust
|
||||
// build subquery with ease
|
||||
let cakes_with_filling: Vec<cake::Model> = cake::Entity::find()
|
||||
.filter(
|
||||
Condition::any().add(
|
||||
cake::Column::Id.in_subquery(
|
||||
Query::select()
|
||||
.column(cake_filling::Column::CakeId)
|
||||
.from(cake_filling::Entity)
|
||||
.to_owned(),
|
||||
),
|
||||
),
|
||||
)
|
||||
.all(&db)
|
||||
.await?;
|
||||
|
||||
```
|
||||
|
||||
[more on SeaQuery](https://docs.rs/sea-query/*/sea_query/)
|
||||
|
||||
3. Testable
|
||||
|
||||
Use mock connections to write unit tests for your logic.
|
||||
|
||||
```rust
|
||||
// Setup mock connection
|
||||
let db = MockDatabase::new(DbBackend::Postgres)
|
||||
.append_query_results(vec![
|
||||
vec![
|
||||
cake::Model {
|
||||
id: 1,
|
||||
name: "New York Cheese".to_owned(),
|
||||
},
|
||||
],
|
||||
])
|
||||
.into_connection();
|
||||
|
||||
// Perform your application logic
|
||||
assert_eq!(
|
||||
cake::Entity::find().one(&db).await?,
|
||||
Some(cake::Model {
|
||||
id: 1,
|
||||
name: "New York Cheese".to_owned(),
|
||||
})
|
||||
);
|
||||
|
||||
// Compare it against the expected transaction log
|
||||
assert_eq!(
|
||||
db.into_transaction_log(),
|
||||
vec![
|
||||
Transaction::from_sql_and_values(
|
||||
DbBackend::Postgres,
|
||||
r#"SELECT "cake"."id", "cake"."name" FROM "cake" LIMIT $1"#,
|
||||
vec![1u64.into()]
|
||||
),
|
||||
]
|
||||
);
|
||||
```
|
||||
|
||||
[more on testing](/docs/write-test/mock)
|
||||
|
||||
4. Service oriented
|
||||
|
||||
Quickly build services that join, filter, sort and paginate data in APIs.
|
||||
|
||||
```rust
|
||||
#[get("/?<page>&<posts_per_page>")]
|
||||
async fn list(
|
||||
conn: Connection<Db>,
|
||||
posts_per_page: Option<usize>,
|
||||
page: Option<usize>,
|
||||
flash: Option<FlashMessage<'_>>,
|
||||
) -> Template {
|
||||
// Set page number and items per page
|
||||
let page = page.unwrap_or(0);
|
||||
let posts_per_page = posts_per_page.unwrap_or(DEFAULT_POSTS_PER_PAGE);
|
||||
|
||||
// Setup paginator
|
||||
let paginator = Post::find()
|
||||
.order_by_asc(post::Column::Id)
|
||||
.paginate(&conn, posts_per_page);
|
||||
let num_pages = paginator.num_pages().await.ok().unwrap();
|
||||
|
||||
// Fetch paginated posts
|
||||
let posts = paginator
|
||||
.fetch_page(page)
|
||||
.await
|
||||
.expect("could not retrieve posts");
|
||||
|
||||
let flash = flash.map(FlashMessage::into_inner);
|
||||
|
||||
Template::render(
|
||||
"index",
|
||||
context! {
|
||||
posts: posts,
|
||||
flash: flash,
|
||||
page: page,
|
||||
posts_per_page: posts_per_page,
|
||||
num_pages: num_pages,
|
||||
},
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
[full Rocket example](https://github.com/SeaQL/sea-orm/tree/master/examples/rocket_example)
|
||||
|
||||
We are building more examples for other web frameworks too.
|
||||
|
||||
## A quick taste of SeaORM
|
||||
|
||||
### Select
|
||||
|
@ -91,7 +91,9 @@ impl Column {
|
||||
},
|
||||
ColumnType::DateTime(_) => quote! { ColumnType::DateTime.def() },
|
||||
ColumnType::Timestamp(_) => quote! { ColumnType::Timestamp.def() },
|
||||
ColumnType::TimestampWithTimeZone(_) => quote! { ColumnType::TimestampWithTimeZone.def() },
|
||||
ColumnType::TimestampWithTimeZone(_) => {
|
||||
quote! { ColumnType::TimestampWithTimeZone.def() }
|
||||
}
|
||||
ColumnType::Time(_) => quote! { ColumnType::Time.def() },
|
||||
ColumnType::Date => quote! { ColumnType::Date.def() },
|
||||
ColumnType::Binary(_) => quote! { ColumnType::Binary.def() },
|
||||
|
@ -334,7 +334,7 @@ mod tests {
|
||||
use sea_query::Query;
|
||||
|
||||
#[test]
|
||||
fn test_in_subquery() {
|
||||
fn test_in_subquery_1() {
|
||||
assert_eq!(
|
||||
cake::Entity::find()
|
||||
.filter(
|
||||
@ -357,6 +357,30 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_in_subquery_2() {
|
||||
assert_eq!(
|
||||
cake::Entity::find()
|
||||
.filter(
|
||||
Condition::any().add(
|
||||
cake::Column::Id.in_subquery(
|
||||
Query::select()
|
||||
.column(cake_filling::Column::CakeId)
|
||||
.from(cake_filling::Entity)
|
||||
.to_owned()
|
||||
)
|
||||
)
|
||||
)
|
||||
.build(DbBackend::MySql)
|
||||
.to_string(),
|
||||
[
|
||||
"SELECT `cake`.`id`, `cake`.`name` FROM `cake`",
|
||||
"WHERE `cake`.`id` IN (SELECT `cake_id` FROM `cake_filling`)",
|
||||
]
|
||||
.join(" ")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_col_from_str() {
|
||||
use std::str::FromStr;
|
||||
|
120
src/lib.rs
120
src/lib.rs
@ -38,18 +38,138 @@
|
||||
//!
|
||||
//! Relying on [SQLx](https://github.com/launchbadge/sqlx), SeaORM is a new library with async support from day 1.
|
||||
//!
|
||||
//! ```
|
||||
//! # use sea_orm::{DbConn, error::*, entity::*, query::*, tests_cfg::*};
|
||||
//! # async fn function(db: &DbConn) -> Result<(), DbErr> {
|
||||
//! // execute multiple queries in parallel
|
||||
//! let cakes_and_fruits: (Vec<cake::Model>, Vec<fruit::Model>) =
|
||||
//! futures::try_join!(Cake::find().all(&db), Fruit::find().all(&db))?;
|
||||
//!
|
||||
//! # Ok(())
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! 2. Dynamic
|
||||
//!
|
||||
//! Built upon [SeaQuery](https://github.com/SeaQL/sea-query), SeaORM allows you to build complex queries without 'fighting the ORM'.
|
||||
//!
|
||||
//! ```
|
||||
//! # use sea_query::Query;
|
||||
//! # use sea_orm::{DbConn, error::*, entity::*, query::*, tests_cfg::*};
|
||||
//! # async fn function(db: &DbConn) -> Result<(), DbErr> {
|
||||
//! // build subquery with ease
|
||||
//! let cakes_with_filling: Vec<cake::Model> = cake::Entity::find()
|
||||
//! .filter(
|
||||
//! Condition::any().add(
|
||||
//! cake::Column::Id.in_subquery(
|
||||
//! Query::select()
|
||||
//! .column(cake_filling::Column::CakeId)
|
||||
//! .from(cake_filling::Entity)
|
||||
//! .to_owned(),
|
||||
//! ),
|
||||
//! ),
|
||||
//! )
|
||||
//! .all(&db)
|
||||
//! .await?;
|
||||
//!
|
||||
//! # Ok(())
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! [more on SeaQuery](https://docs.rs/sea-query/*/sea_query/)
|
||||
//!
|
||||
//! 3. Testable
|
||||
//!
|
||||
//! Use mock connections to write unit tests for your logic.
|
||||
//!
|
||||
//! ```
|
||||
//! # use sea_orm::{error::*, entity::*, query::*, tests_cfg::*, DbConn, MockDatabase, Transaction, DbBackend};
|
||||
//! # async fn function(db: &DbConn) -> Result<(), DbErr> {
|
||||
//! // Setup mock connection
|
||||
//! let db = MockDatabase::new(DbBackend::Postgres)
|
||||
//! .append_query_results(vec![
|
||||
//! vec![
|
||||
//! cake::Model {
|
||||
//! id: 1,
|
||||
//! name: "New York Cheese".to_owned(),
|
||||
//! },
|
||||
//! ],
|
||||
//! ])
|
||||
//! .into_connection();
|
||||
//!
|
||||
//! // Perform your application logic
|
||||
//! assert_eq!(
|
||||
//! cake::Entity::find().one(&db).await?,
|
||||
//! Some(cake::Model {
|
||||
//! id: 1,
|
||||
//! name: "New York Cheese".to_owned(),
|
||||
//! })
|
||||
//! );
|
||||
//!
|
||||
//! // Compare it against the expected transaction log
|
||||
//! assert_eq!(
|
||||
//! db.into_transaction_log(),
|
||||
//! vec![
|
||||
//! Transaction::from_sql_and_values(
|
||||
//! DbBackend::Postgres,
|
||||
//! r#"SELECT "cake"."id", "cake"."name" FROM "cake" LIMIT $1"#,
|
||||
//! vec![1u64.into()]
|
||||
//! ),
|
||||
//! ]
|
||||
//! );
|
||||
//! # Ok(())
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! [more on testing](/docs/write-test/mock)
|
||||
//!
|
||||
//! 4. Service oriented
|
||||
//!
|
||||
//! Quickly build services that join, filter, sort and paginate data in APIs.
|
||||
//!
|
||||
//! ```ignore
|
||||
//! #[get("/?<page>&<posts_per_page>")]
|
||||
//! async fn list(
|
||||
//! conn: Connection<Db>,
|
||||
//! posts_per_page: Option<usize>,
|
||||
//! page: Option<usize>,
|
||||
//! flash: Option<FlashMessage<'_>>,
|
||||
//! ) -> Template {
|
||||
//! // Set page number and items per page
|
||||
//! let page = page.unwrap_or(0);
|
||||
//! let posts_per_page = posts_per_page.unwrap_or(DEFAULT_POSTS_PER_PAGE);
|
||||
//!
|
||||
//! // Setup paginator
|
||||
//! let paginator = Post::find()
|
||||
//! .order_by_asc(post::Column::Id)
|
||||
//! .paginate(&conn, posts_per_page);
|
||||
//! let num_pages = paginator.num_pages().await.ok().unwrap();
|
||||
//!
|
||||
//! // Fetch paginated posts
|
||||
//! let posts = paginator
|
||||
//! .fetch_page(page)
|
||||
//! .await
|
||||
//! .expect("could not retrieve posts");
|
||||
//!
|
||||
//! let flash = flash.map(FlashMessage::into_inner);
|
||||
//!
|
||||
//! Template::render(
|
||||
//! "index",
|
||||
//! context! {
|
||||
//! posts: posts,
|
||||
//! flash: flash,
|
||||
//! page: page,
|
||||
//! posts_per_page: posts_per_page,
|
||||
//! num_pages: num_pages,
|
||||
//! },
|
||||
//! )
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! [full Rocket example](https://github.com/SeaQL/sea-orm/tree/master/examples/rocket_example)
|
||||
//!
|
||||
//! We are building more examples for other web frameworks too.
|
||||
//!
|
||||
//! ## A quick taste of SeaORM
|
||||
//!
|
||||
//! ### Select
|
||||
|
Loading…
x
Reference in New Issue
Block a user