Merge branch 'master' into ss/rocket-example
This commit is contained in:
commit
3f6b2e3516
39
ARCHITECTURE.md
Normal file
39
ARCHITECTURE.md
Normal file
@ -0,0 +1,39 @@
|
||||
# Architecture
|
||||
|
||||
To understand the architecture of SeaORM, let's discuss what is an ORM. ORM exists to provide abstractions over common operations you would do against a database and hide the implementation details like the actual SQL queries.
|
||||
|
||||
With a good ORM, you shouldn't bother to look under the API surface. Until you do. I hear you say *'abstraction leaks'*, and yes, it does.
|
||||
|
||||
The approach SeaORM takes is **'layered abstraction'**, where you'd dig one layer beneath if you want to. That's why we made SeaQuery into a standalone repository. It's useful on its own, and with a public API surface and a separate namespace, it's far more difficult to create confusing internal APIs than a monolithic approach.
|
||||
|
||||
The central idea in SeaORM is nearly everything is runtime configurable. At compile time, it does not know what the underlying database is.
|
||||
|
||||
What benefits does database-agnostic bring? For example, you can:
|
||||
|
||||
1. Make your app work on any database, depending on runtime configuration
|
||||
1. Use the same models and transfer them across different databases
|
||||
1. Share entities across different projects by creating a 'data structure crate', where the database is chosen by downstream 'behaviour crates'
|
||||
|
||||
The API of SeaORM is not a thin shell, but consist of layers, with each layer underneath being less abstract.
|
||||
|
||||
There are different stages when the API is being utilized.
|
||||
|
||||
So there are two dimensions to navigate the SeaORM code base, **'stage'** and **'abstractness'**.
|
||||
|
||||
First is the declaration stage. Entities and relations among them are being defined with the `EntityTrait`, `ColumnTrait` & `RelationTrait` etc.
|
||||
|
||||
Second is the query building stage.
|
||||
|
||||
The top most layer is `Entity`'s `find*`, `insert`, `update` & `delete` methods, where you can intuitively perform basic CRUD operations.
|
||||
|
||||
One layer down, is the `Select`, `Insert`, `Update` & `Delete` structs, where they each have their own API for more advanced operations.
|
||||
|
||||
One layer down, is the SeaQuery `SelectStatement`, `InsertStatement`, `UpdateStatement` & `DeleteStatement`, where they have a rich API for you to fiddle with the SQL syntax tree.
|
||||
|
||||
Third is the execution stage. A separate set of structs, `Selector`, `Inserter`, `Updater` & `Deleter`, are responsible for executing the statements against a database connection.
|
||||
|
||||
Finally is the resolution stage, when query results are converted into Rust structs for consumption.
|
||||
|
||||
Because only the execution and resolution stages are database specific, we have the possibility to use a different driver by replacing those.
|
||||
|
||||
I imagine some day, we will support a number of databases, with a matrix of different syntaxes, protocols and form-factors.
|
@ -1,4 +1,4 @@
|
||||
# Design Goals
|
||||
# Design
|
||||
|
||||
We are heavily inspired by ActiveRecord, Eloquent and TypeORM.
|
||||
|
||||
@ -20,7 +20,7 @@ After some bitterness we realized it is not possible to capture everything compi
|
||||
want to encounter problems at run time either. The solution is to perform checking at 'test time' to
|
||||
uncover problems. These checks will be removed at production so there will be no run time penalty.
|
||||
|
||||
## Readability
|
||||
## API style
|
||||
|
||||
### Turbofish and inference
|
||||
|
||||
@ -65,4 +65,35 @@ has_many(cake::Entity, cake::Column::Id, fruit::Column::CakeId)
|
||||
we'd prefer having a builder and stating the params explicitly:
|
||||
```rust
|
||||
has_many(cake::Entity).from(cake::Column::Id).to(fruit::Column::CakeId)
|
||||
```
|
||||
|
||||
### Method overloading
|
||||
|
||||
Consider the following two methods, which accept the same parameter but in different forms:
|
||||
|
||||
```rust
|
||||
fn method_with_model(m: Model) { ... }
|
||||
fn method_with_active_model(a: ActiveModel) { ... }
|
||||
```
|
||||
|
||||
We would define a trait
|
||||
|
||||
```rust
|
||||
pub trait IntoActiveModel {
|
||||
fn into_active_model(self) -> ActiveModel;
|
||||
}
|
||||
```
|
||||
|
||||
Such that `Model` and `ActiveModel` both impl this trait.
|
||||
|
||||
In this way, we can overload the two methods:
|
||||
|
||||
```rust
|
||||
pub fn method<A>(a: A)
|
||||
where
|
||||
A: IntoActiveModel,
|
||||
{
|
||||
let a: ActiveModel = a.into_active_model();
|
||||
...
|
||||
}
|
||||
```
|
10
README.md
10
README.md
@ -25,7 +25,7 @@ This is an early release of SeaORM, the API is not stable yet.
|
||||
```
|
||||
|
||||
[](https://www.sea-ql.org/SeaORM/docs/index)
|
||||
[](https://github.com/SeaQL/sea-orm/tree/master/examples/sqlx)
|
||||
[](https://github.com/SeaQL/sea-orm/tree/master/examples)
|
||||
[](https://github.com/SeaQL/sea-orm/issues/37)
|
||||
[](https://discord.com/invite/uCPdDXzbdv)
|
||||
|
||||
@ -108,7 +108,7 @@ let pear: fruit::ActiveModel = Fruit::update(pear).exec(db).await?;
|
||||
|
||||
// update many: UPDATE "fruit" SET "cake_id" = NULL WHERE "fruit"."name" LIKE '%Apple%'
|
||||
Fruit::update_many()
|
||||
.col_expr(fruit::Column::CakeId, Expr::value(Value::Null))
|
||||
.col_expr(fruit::Column::CakeId, Expr::value(Value::Int(None)))
|
||||
.filter(fruit::Column::Name.contains("Apple"))
|
||||
.exec(db)
|
||||
.await?;
|
||||
@ -148,6 +148,12 @@ fruit::Entity::delete_many()
|
||||
.await?;
|
||||
|
||||
```
|
||||
|
||||
## Learn More
|
||||
|
||||
1. [Design](https://github.com/SeaQL/sea-orm/tree/master/DESIGN.md)
|
||||
1. [Architecture](https://github.com/SeaQL/sea-orm/tree/master/ARCHITECTURE.md)
|
||||
|
||||
## License
|
||||
|
||||
Licensed under either of
|
||||
|
@ -25,7 +25,7 @@
|
||||
//! ```
|
||||
//!
|
||||
//! [](https://www.sea-ql.org/SeaORM/docs/index)
|
||||
//! [](https://github.com/SeaQL/sea-orm/tree/master/examples/sqlx)
|
||||
//! [](https://github.com/SeaQL/sea-orm/tree/master/examples)
|
||||
//! [](https://github.com/SeaQL/sea-orm/issues/37)
|
||||
//! [](https://discord.com/invite/uCPdDXzbdv)
|
||||
//!
|
||||
@ -180,6 +180,12 @@
|
||||
//! # Ok(())
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! ## Learn More
|
||||
//!
|
||||
//! 1. [Design](https://github.com/SeaQL/sea-orm/tree/master/DESIGN.md)
|
||||
//! 1. [Architecture](https://github.com/SeaQL/sea-orm/tree/master/ARCHITECTURE.md)
|
||||
//!
|
||||
//! ## License
|
||||
//!
|
||||
//! Licensed under either of
|
||||
|
Loading…
x
Reference in New Issue
Block a user