Restore example
This commit is contained in:
parent
1b47f896a7
commit
e228ada74a
@ -4,6 +4,7 @@ members = [
|
|||||||
"sea-orm-macros",
|
"sea-orm-macros",
|
||||||
"sea-orm-codegen",
|
"sea-orm-codegen",
|
||||||
"sea-orm-cli",
|
"sea-orm-cli",
|
||||||
|
"examples/sqlx",
|
||||||
]
|
]
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
|
13
examples/sqlx/Cargo.toml
Normal file
13
examples/sqlx/Cargo.toml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
[package]
|
||||||
|
name = "sea-orm-sqlx-example"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2018"
|
||||||
|
publish = false
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
async-std = { version = "^1.9", features = [ "attributes" ] }
|
||||||
|
sea-orm = { path = "../../", features = [ "sqlx-all", "runtime-async-std-native-tls" ] }
|
||||||
|
serde_json = { version = "^1" }
|
||||||
|
futures = { version = "^0.3" }
|
||||||
|
async-stream = { version = "^0.3" }
|
||||||
|
futures-util = { version = "^0.3" }
|
141
examples/sqlx/Readme.md
Normal file
141
examples/sqlx/Readme.md
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
# SeaORM SQLx MySql example
|
||||||
|
|
||||||
|
Prepare:
|
||||||
|
|
||||||
|
Setup a test database and configure the connection string in `main.rs`.
|
||||||
|
Run `bakery.sql` to setup the test table and data.
|
||||||
|
|
||||||
|
Running:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cargo run
|
||||||
|
```
|
||||||
|
|
||||||
|
All about selects:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
SqlxMySqlPoolConnection
|
||||||
|
|
||||||
|
===== =====
|
||||||
|
|
||||||
|
find all cakes: SELECT `cake`.`id`, `cake`.`name` FROM `cake`
|
||||||
|
|
||||||
|
Model { id: 1, name: "New York Cheese" }
|
||||||
|
|
||||||
|
Model { id: 2, name: "Chocolate Forest" }
|
||||||
|
|
||||||
|
find all fruits: SELECT `fruit`.`id`, `fruit`.`name`, `fruit`.`cake_id` FROM `fruit`
|
||||||
|
|
||||||
|
Model { id: 1, name: "Blueberry", cake_id: Some(1) }
|
||||||
|
|
||||||
|
Model { id: 2, name: "Rasberry", cake_id: Some(1) }
|
||||||
|
|
||||||
|
Model { id: 3, name: "Strawberry", cake_id: Some(2) }
|
||||||
|
|
||||||
|
Model { id: 4, name: "Apple", cake_id: None }
|
||||||
|
|
||||||
|
Model { id: 5, name: "Banana", cake_id: None }
|
||||||
|
|
||||||
|
Model { id: 6, name: "Cherry", cake_id: None }
|
||||||
|
|
||||||
|
Model { id: 7, name: "Lemon", cake_id: None }
|
||||||
|
|
||||||
|
Model { id: 8, name: "Orange", cake_id: None }
|
||||||
|
|
||||||
|
Model { id: 9, name: "Pineapple", cake_id: None }
|
||||||
|
|
||||||
|
===== =====
|
||||||
|
|
||||||
|
find cakes and fruits: SELECT `cake`.`id` AS `A_id`, `cake`.`name` AS `A_name`, `fruit`.`id` AS `B_id`, `fruit`.`name` AS `B_name`, `fruit`.`cake_id` AS `B_cake_id` FROM `cake` LEFT JOIN `fruit` ON `cake`.`id` = `fruit`.`cake_id`
|
||||||
|
|
||||||
|
(Model { id: 1, name: "New York Cheese" }, Some(Model { id: 1, name: "Blueberry", cake_id: Some(1) }))
|
||||||
|
|
||||||
|
(Model { id: 1, name: "New York Cheese" }, Some(Model { id: 2, name: "Rasberry", cake_id: Some(1) }))
|
||||||
|
|
||||||
|
(Model { id: 2, name: "Chocolate Forest" }, Some(Model { id: 3, name: "Strawberry", cake_id: Some(2) }))
|
||||||
|
|
||||||
|
===== =====
|
||||||
|
|
||||||
|
find one by primary key: SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`id` = 1 LIMIT 1
|
||||||
|
|
||||||
|
Model { id: 1, name: "New York Cheese" }
|
||||||
|
|
||||||
|
find one by name: SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`name` LIKE '%chocolate%' LIMIT 1
|
||||||
|
|
||||||
|
Some(Model { id: 2, name: "Chocolate Forest" })
|
||||||
|
|
||||||
|
find models belong to: SELECT `fruit`.`id`, `fruit`.`name`, `fruit`.`cake_id` FROM `fruit` INNER JOIN `cake` ON `cake`.`id` = `fruit`.`cake_id` WHERE `cake`.`id` = 1
|
||||||
|
|
||||||
|
Model { id: 1, name: "Blueberry", cake_id: Some(1) }
|
||||||
|
|
||||||
|
Model { id: 2, name: "Rasberry", cake_id: Some(1) }
|
||||||
|
|
||||||
|
===== =====
|
||||||
|
|
||||||
|
count fruits by cake: SELECT `cake`.`name`, COUNT(`fruit`.`id`) AS `num_of_fruits` FROM `cake` LEFT JOIN `fruit` ON `cake`.`id` = `fruit`.`cake_id` GROUP BY `cake`.`name`
|
||||||
|
|
||||||
|
SelectResult { name: "New York Cheese", num_of_fruits: 2 }
|
||||||
|
|
||||||
|
SelectResult { name: "Chocolate Forest", num_of_fruits: 1 }
|
||||||
|
|
||||||
|
===== =====
|
||||||
|
|
||||||
|
find cakes and fillings: SELECT `cake`.`id` AS `A_id`, `cake`.`name` AS `A_name`, `filling`.`id` AS `B_id`, `filling`.`name` AS `B_name` FROM `cake` LEFT JOIN `cake_filling` ON `cake`.`id` = `cake_filling`.`cake_id` LEFT JOIN `filling` ON `cake_filling`.`filling_id` = `filling`.`id` ORDER BY `cake`.`id` ASC
|
||||||
|
|
||||||
|
(Model { id: 1, name: "New York Cheese" }, [Model { id: 1, name: "Vanilla" }, Model { id: 2, name: "Lemon" }])
|
||||||
|
|
||||||
|
(Model { id: 2, name: "Chocolate Forest" }, [Model { id: 2, name: "Lemon" }, Model { id: 3, name: "Mango" }])
|
||||||
|
|
||||||
|
find fillings for cheese cake: SELECT `cake`.`id`, `cake`.`name` FROM `cake` WHERE `cake`.`id` = 1 LIMIT 1
|
||||||
|
SELECT `filling`.`id`, `filling`.`name` FROM `filling` INNER JOIN `cake_filling` ON `cake_filling`.`filling_id` = `filling`.`id` INNER JOIN `cake` ON `cake`.`id` = `cake_filling`.`cake_id` WHERE `cake`.`id` = 1
|
||||||
|
|
||||||
|
Model { id: 1, name: "Vanilla" }
|
||||||
|
|
||||||
|
Model { id: 2, name: "Lemon" }
|
||||||
|
|
||||||
|
find cakes for lemon: SELECT `filling`.`id`, `filling`.`name` FROM `filling` WHERE `filling`.`id` = 2 LIMIT 1
|
||||||
|
SELECT `cake`.`id`, `cake`.`name` FROM `cake` INNER JOIN `cake_filling` ON `cake_filling`.`cake_id` = `cake`.`id` INNER JOIN `filling` ON `filling`.`id` = `cake_filling`.`filling_id` WHERE `filling`.`id` = 2
|
||||||
|
|
||||||
|
Model { id: 1, name: "New York Cheese" }
|
||||||
|
|
||||||
|
Model { id: 2, name: "Chocolate Forest" }
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
All about operations:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
INSERT INTO `fruit` (`name`) VALUES ('pear')
|
||||||
|
|
||||||
|
Inserted: InsertResult { last_insert_id: 21 }
|
||||||
|
|
||||||
|
SELECT `fruit`.`id`, `fruit`.`name`, `fruit`.`cake_id` FROM `fruit` WHERE `fruit`.`id` = 21 LIMIT 1
|
||||||
|
|
||||||
|
Pear: Some(Model { id: 21, name: "pear", cake_id: None })
|
||||||
|
|
||||||
|
UPDATE `fruit` SET `name` = 'Sweet pear' WHERE `fruit`.`id` = 21
|
||||||
|
|
||||||
|
Updated: ActiveModel { id: ActiveValue { value: 21, state: Unchanged }, name: ActiveValue { value: "Sweet pear", state: Set }, cake_id: ActiveValue { value: None, state: Unchanged } }
|
||||||
|
|
||||||
|
===== =====
|
||||||
|
|
||||||
|
INSERT INTO `fruit` (`name`) VALUES ('banana')
|
||||||
|
SELECT `fruit`.`id`, `fruit`.`name`, `fruit`.`cake_id` FROM `fruit` WHERE `fruit`.`id` = 22 LIMIT 1
|
||||||
|
|
||||||
|
Inserted: ActiveModel { id: ActiveValue { value: 22, state: Unchanged }, name: ActiveValue { value: "banana", state: Unchanged }, cake_id: ActiveValue { value: None, state: Unchanged } }
|
||||||
|
|
||||||
|
UPDATE `fruit` SET `name` = 'banana banana' WHERE `fruit`.`id` = 22
|
||||||
|
|
||||||
|
Updated: ActiveModel { id: ActiveValue { value: 22, state: Unchanged }, name: ActiveValue { value: "banana banana", state: Set }, cake_id: ActiveValue { value: None, state: Unchanged } }
|
||||||
|
|
||||||
|
DELETE FROM `fruit` WHERE `fruit`.`id` = 22
|
||||||
|
|
||||||
|
Deleted: DeleteResult { rows_affected: 1 }
|
||||||
|
|
||||||
|
===== =====
|
||||||
|
|
||||||
|
INSERT INTO `fruit` (`name`) VALUES ('pineapple')
|
||||||
|
SELECT `fruit`.`id`, `fruit`.`name`, `fruit`.`cake_id` FROM `fruit` WHERE `fruit`.`id` = 23 LIMIT 1
|
||||||
|
|
||||||
|
Saved: ActiveModel { id: ActiveValue { value: 23, state: Unchanged }, name: ActiveValue { value: "pineapple", state: Unchanged } }
|
||||||
|
```
|
@ -4,7 +4,7 @@ CREATE TABLE `cake` (
|
|||||||
`id` int NOT NULL AUTO_INCREMENT,
|
`id` int NOT NULL AUTO_INCREMENT,
|
||||||
`name` varchar(255) NOT NULL,
|
`name` varchar(255) NOT NULL,
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
);
|
||||||
|
|
||||||
INSERT INTO `cake` (`id`, `name`) VALUES
|
INSERT INTO `cake` (`id`, `name`) VALUES
|
||||||
(1, 'New York Cheese'),
|
(1, 'New York Cheese'),
|
||||||
@ -18,7 +18,7 @@ CREATE TABLE `fruit` (
|
|||||||
`cake_id` int DEFAULT NULL,
|
`cake_id` int DEFAULT NULL,
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
CONSTRAINT `fk-fruit-cake` FOREIGN KEY (`cake_id`) REFERENCES `cake` (`id`)
|
CONSTRAINT `fk-fruit-cake` FOREIGN KEY (`cake_id`) REFERENCES `cake` (`id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
);
|
||||||
|
|
||||||
INSERT INTO `fruit` (`id`, `name`, `cake_id`) VALUES
|
INSERT INTO `fruit` (`id`, `name`, `cake_id`) VALUES
|
||||||
(1, 'Blueberry', 1),
|
(1, 'Blueberry', 1),
|
||||||
@ -39,7 +39,7 @@ CREATE TABLE `filling` (
|
|||||||
`id` int NOT NULL AUTO_INCREMENT,
|
`id` int NOT NULL AUTO_INCREMENT,
|
||||||
`name` varchar(255) NOT NULL,
|
`name` varchar(255) NOT NULL,
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
);
|
||||||
|
|
||||||
INSERT INTO `filling` (`id`, `name`) VALUES
|
INSERT INTO `filling` (`id`, `name`) VALUES
|
||||||
(1, 'Vanilla'),
|
(1, 'Vanilla'),
|
||||||
@ -54,7 +54,7 @@ CREATE TABLE `cake_filling` (
|
|||||||
PRIMARY KEY (`cake_id`, `filling_id`),
|
PRIMARY KEY (`cake_id`, `filling_id`),
|
||||||
CONSTRAINT `fk-cake_filling-cake` FOREIGN KEY (`cake_id`) REFERENCES `cake` (`id`),
|
CONSTRAINT `fk-cake_filling-cake` FOREIGN KEY (`cake_id`) REFERENCES `cake` (`id`),
|
||||||
CONSTRAINT `fk-cake_filling-filling` FOREIGN KEY (`filling_id`) REFERENCES `filling` (`id`)
|
CONSTRAINT `fk-cake_filling-filling` FOREIGN KEY (`filling_id`) REFERENCES `filling` (`id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
);
|
||||||
|
|
||||||
INSERT INTO `cake_filling` (`cake_id`, `filling_id`) VALUES
|
INSERT INTO `cake_filling` (`cake_id`, `filling_id`) VALUES
|
||||||
(1, 1),
|
(1, 1),
|
7
examples/sqlx/import.sh
Normal file
7
examples/sqlx/import.sh
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
cp ../../src/tests_cfg/cake.rs src/example_cake.rs
|
||||||
|
cp ../../src/tests_cfg/fruit.rs src/example_fruit.rs
|
||||||
|
cp ../../src/tests_cfg/filling.rs src/example_filling.rs
|
||||||
|
cp ../../src/tests_cfg/cake_filling.rs src/example_cake_filling.rs
|
||||||
|
|
||||||
|
sed -i 's/^use crate::/use sea_orm::/g' src/*.rs
|
||||||
|
sed -i '/^use crate as sea_orm;/d' src/*.rs
|
4
examples/sqlx/src/entities.rs
Normal file
4
examples/sqlx/src/entities.rs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
pub use super::cake::Entity as Cake;
|
||||||
|
pub use super::cake_filling::Entity as CakeFilling;
|
||||||
|
pub use super::filling::Entity as Filling;
|
||||||
|
pub use super::fruit::Entity as Fruit;
|
75
examples/sqlx/src/example_cake.rs
Normal file
75
examples/sqlx/src/example_cake.rs
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Default, Debug, DeriveEntity)]
|
||||||
|
pub struct Entity;
|
||||||
|
|
||||||
|
impl EntityName for Entity {
|
||||||
|
fn table_name(&self) -> &str {
|
||||||
|
"cake"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)]
|
||||||
|
pub struct Model {
|
||||||
|
pub id: i32,
|
||||||
|
pub name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
|
||||||
|
pub enum Column {
|
||||||
|
Id,
|
||||||
|
Name,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
|
||||||
|
pub enum PrimaryKey {
|
||||||
|
Id,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrimaryKeyTrait for PrimaryKey {
|
||||||
|
fn auto_increment() -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter)]
|
||||||
|
pub enum Relation {
|
||||||
|
Fruit,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ColumnTrait for Column {
|
||||||
|
type EntityName = Entity;
|
||||||
|
|
||||||
|
fn def(&self) -> ColumnDef {
|
||||||
|
match self {
|
||||||
|
Self::Id => ColumnType::Integer.def(),
|
||||||
|
Self::Name => ColumnType::String(None).def(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RelationTrait for Relation {
|
||||||
|
fn def(&self) -> RelationDef {
|
||||||
|
match self {
|
||||||
|
Self::Fruit => Entity::has_many(super::fruit::Entity).into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::fruit::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Fruit.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::filling::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
super::cake_filling::Relation::Filling.def()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn via() -> Option<RelationDef> {
|
||||||
|
Some(super::cake_filling::Relation::Cake.def().rev())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
68
examples/sqlx/src/example_cake_filling.rs
Normal file
68
examples/sqlx/src/example_cake_filling.rs
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Default, Debug, DeriveEntity)]
|
||||||
|
pub struct Entity;
|
||||||
|
|
||||||
|
impl EntityName for Entity {
|
||||||
|
fn table_name(&self) -> &str {
|
||||||
|
"cake_filling"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)]
|
||||||
|
pub struct Model {
|
||||||
|
pub cake_id: i32,
|
||||||
|
pub filling_id: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
|
||||||
|
pub enum Column {
|
||||||
|
CakeId,
|
||||||
|
FillingId,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
|
||||||
|
pub enum PrimaryKey {
|
||||||
|
CakeId,
|
||||||
|
FillingId,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrimaryKeyTrait for PrimaryKey {
|
||||||
|
fn auto_increment() -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter)]
|
||||||
|
pub enum Relation {
|
||||||
|
Cake,
|
||||||
|
Filling,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ColumnTrait for Column {
|
||||||
|
type EntityName = Entity;
|
||||||
|
|
||||||
|
fn def(&self) -> ColumnDef {
|
||||||
|
match self {
|
||||||
|
Self::CakeId => ColumnType::Integer.def(),
|
||||||
|
Self::FillingId => ColumnType::Integer.def(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RelationTrait for Relation {
|
||||||
|
fn def(&self) -> RelationDef {
|
||||||
|
match self {
|
||||||
|
Self::Cake => Entity::belongs_to(super::cake::Entity)
|
||||||
|
.from(Column::CakeId)
|
||||||
|
.to(super::cake::Column::Id)
|
||||||
|
.into(),
|
||||||
|
Self::Filling => Entity::belongs_to(super::filling::Entity)
|
||||||
|
.from(Column::FillingId)
|
||||||
|
.to(super::filling::Column::Id)
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
65
examples/sqlx/src/example_filling.rs
Normal file
65
examples/sqlx/src/example_filling.rs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Default, Debug, DeriveEntity)]
|
||||||
|
pub struct Entity;
|
||||||
|
|
||||||
|
impl EntityName for Entity {
|
||||||
|
fn table_name(&self) -> &str {
|
||||||
|
"filling"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)]
|
||||||
|
pub struct Model {
|
||||||
|
pub id: i32,
|
||||||
|
pub name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
|
||||||
|
pub enum Column {
|
||||||
|
Id,
|
||||||
|
Name,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
|
||||||
|
pub enum PrimaryKey {
|
||||||
|
Id,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrimaryKeyTrait for PrimaryKey {
|
||||||
|
fn auto_increment() -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter)]
|
||||||
|
pub enum Relation {}
|
||||||
|
|
||||||
|
impl ColumnTrait for Column {
|
||||||
|
type EntityName = Entity;
|
||||||
|
|
||||||
|
fn def(&self) -> ColumnDef {
|
||||||
|
match self {
|
||||||
|
Self::Id => ColumnType::Integer.def(),
|
||||||
|
Self::Name => ColumnType::String(None).def(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RelationTrait for Relation {
|
||||||
|
fn def(&self) -> RelationDef {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::cake::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
super::cake_filling::Relation::Cake.def()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn via() -> Option<RelationDef> {
|
||||||
|
Some(super::cake_filling::Relation::Filling.def().rev())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
71
examples/sqlx/src/example_fruit.rs
Normal file
71
examples/sqlx/src/example_fruit.rs
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Default, Debug, DeriveEntity)]
|
||||||
|
pub struct Entity;
|
||||||
|
|
||||||
|
impl EntityName for Entity {
|
||||||
|
fn table_name(&self) -> &str {
|
||||||
|
"fruit"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)]
|
||||||
|
pub struct Model {
|
||||||
|
pub id: i32,
|
||||||
|
pub name: String,
|
||||||
|
pub cake_id: Option<i32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
|
||||||
|
pub enum Column {
|
||||||
|
Id,
|
||||||
|
Name,
|
||||||
|
CakeId,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
|
||||||
|
pub enum PrimaryKey {
|
||||||
|
Id,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrimaryKeyTrait for PrimaryKey {
|
||||||
|
fn auto_increment() -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter)]
|
||||||
|
pub enum Relation {
|
||||||
|
Cake,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ColumnTrait for Column {
|
||||||
|
type EntityName = Entity;
|
||||||
|
|
||||||
|
fn def(&self) -> ColumnDef {
|
||||||
|
match self {
|
||||||
|
Self::Id => ColumnType::Integer.def(),
|
||||||
|
Self::Name => ColumnType::String(None).def(),
|
||||||
|
Self::CakeId => ColumnType::Integer.def(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RelationTrait for Relation {
|
||||||
|
fn def(&self) -> RelationDef {
|
||||||
|
match self {
|
||||||
|
Self::Cake => Entity::belongs_to(super::cake::Entity)
|
||||||
|
.from(Column::CakeId)
|
||||||
|
.to(super::cake::Column::Id)
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::cake::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Cake.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
34
examples/sqlx/src/main.rs
Normal file
34
examples/sqlx/src/main.rs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
use sea_orm::Database;
|
||||||
|
|
||||||
|
mod entities;
|
||||||
|
mod example_cake;
|
||||||
|
mod example_cake_filling;
|
||||||
|
mod example_filling;
|
||||||
|
mod example_fruit;
|
||||||
|
mod operation;
|
||||||
|
mod select;
|
||||||
|
|
||||||
|
use entities::*;
|
||||||
|
use example_cake as cake;
|
||||||
|
use example_cake_filling as cake_filling;
|
||||||
|
use example_filling as filling;
|
||||||
|
use example_fruit as fruit;
|
||||||
|
use operation::*;
|
||||||
|
use select::*;
|
||||||
|
|
||||||
|
#[async_std::main]
|
||||||
|
async fn main() {
|
||||||
|
let db = Database::connect("sql://sea:sea@localhost/bakery")
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
println!("{:?}\n", db);
|
||||||
|
|
||||||
|
println!("===== =====\n");
|
||||||
|
|
||||||
|
all_about_select(&db).await.unwrap();
|
||||||
|
|
||||||
|
println!("===== =====\n");
|
||||||
|
|
||||||
|
all_about_operation(&db).await.unwrap();
|
||||||
|
}
|
94
examples/sqlx/src/operation.rs
Normal file
94
examples/sqlx/src/operation.rs
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
use super::*;
|
||||||
|
use sea_orm::{entity::*, error::*, query::*, DbConn};
|
||||||
|
|
||||||
|
pub async fn all_about_operation(db: &DbConn) -> Result<(), DbErr> {
|
||||||
|
insert_and_update(db).await?;
|
||||||
|
|
||||||
|
println!("===== =====\n");
|
||||||
|
|
||||||
|
save_active_model(db).await?;
|
||||||
|
|
||||||
|
println!("===== =====\n");
|
||||||
|
|
||||||
|
save_custom_active_model(db).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn insert_and_update(db: &DbConn) -> Result<(), DbErr> {
|
||||||
|
let pear = fruit::ActiveModel {
|
||||||
|
name: Set("pear".to_owned()),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
let res: InsertResult = Fruit::insert(pear).exec(db).await?;
|
||||||
|
|
||||||
|
println!();
|
||||||
|
println!("Inserted: last_insert_id = {}\n", res.last_insert_id);
|
||||||
|
|
||||||
|
let pear: Option<fruit::Model> = Fruit::find_by_id(res.last_insert_id).one(db).await?;
|
||||||
|
|
||||||
|
println!();
|
||||||
|
println!("Pear: {:?}\n", pear);
|
||||||
|
|
||||||
|
let mut pear: fruit::ActiveModel = pear.unwrap().into();
|
||||||
|
pear.name = Set("Sweet pear".to_owned());
|
||||||
|
|
||||||
|
let pear: fruit::ActiveModel = Fruit::update(pear).exec(db).await?;
|
||||||
|
|
||||||
|
println!();
|
||||||
|
println!("Updated: {:?}\n", pear);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn save_active_model(db: &DbConn) -> Result<(), DbErr> {
|
||||||
|
let banana = fruit::ActiveModel {
|
||||||
|
name: Set("Banana".to_owned()),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
let mut banana = banana.save(db).await?;
|
||||||
|
|
||||||
|
println!();
|
||||||
|
println!("Inserted: {:?}\n", banana);
|
||||||
|
|
||||||
|
banana.name = Set("Banana Mongo".to_owned());
|
||||||
|
|
||||||
|
let banana = banana.save(db).await?;
|
||||||
|
|
||||||
|
println!();
|
||||||
|
println!("Updated: {:?}\n", banana);
|
||||||
|
|
||||||
|
let result = banana.delete(db).await?;
|
||||||
|
|
||||||
|
println!();
|
||||||
|
println!("Deleted: {:?}\n", result);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
mod form {
|
||||||
|
use super::fruit::*;
|
||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
|
||||||
|
#[derive(
|
||||||
|
Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel, DeriveActiveModelBehavior,
|
||||||
|
)]
|
||||||
|
pub struct Model {
|
||||||
|
pub id: i32,
|
||||||
|
pub name: String,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn save_custom_active_model(db: &DbConn) -> Result<(), DbErr> {
|
||||||
|
let pineapple = form::ActiveModel {
|
||||||
|
id: Unset(None),
|
||||||
|
name: Set("Pineapple".to_owned()),
|
||||||
|
};
|
||||||
|
|
||||||
|
let pineapple = pineapple.save(db).await?;
|
||||||
|
|
||||||
|
println!();
|
||||||
|
println!("Saved: {:?}\n", pineapple);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
310
examples/sqlx/src/select.rs
Normal file
310
examples/sqlx/src/select.rs
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
use super::*;
|
||||||
|
use sea_orm::{entity::*, error::*, query::*, DbConn, FromQueryResult};
|
||||||
|
|
||||||
|
pub async fn all_about_select(db: &DbConn) -> Result<(), DbErr> {
|
||||||
|
find_all(db).await?;
|
||||||
|
|
||||||
|
println!("===== =====\n");
|
||||||
|
|
||||||
|
find_together(db).await?;
|
||||||
|
|
||||||
|
println!("===== =====\n");
|
||||||
|
|
||||||
|
find_one(db).await?;
|
||||||
|
|
||||||
|
println!("===== =====\n");
|
||||||
|
|
||||||
|
count_fruits_by_cake(db).await?;
|
||||||
|
|
||||||
|
println!("===== =====\n");
|
||||||
|
|
||||||
|
find_many_to_many(db).await?;
|
||||||
|
|
||||||
|
if false {
|
||||||
|
println!("===== =====\n");
|
||||||
|
|
||||||
|
all_about_select_json(db).await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("===== =====\n");
|
||||||
|
|
||||||
|
find_all_stream(&db).await.unwrap();
|
||||||
|
|
||||||
|
println!("===== =====\n");
|
||||||
|
|
||||||
|
find_first_page(&db).await.unwrap();
|
||||||
|
|
||||||
|
println!("===== =====\n");
|
||||||
|
|
||||||
|
find_num_pages(&db).await.unwrap();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn find_all(db: &DbConn) -> Result<(), DbErr> {
|
||||||
|
print!("find all cakes: ");
|
||||||
|
|
||||||
|
let cakes: Vec<cake::Model> = Cake::find().all(db).await?;
|
||||||
|
|
||||||
|
println!();
|
||||||
|
for cc in cakes.iter() {
|
||||||
|
println!("{:?}\n", cc);
|
||||||
|
}
|
||||||
|
|
||||||
|
print!("find all fruits: ");
|
||||||
|
|
||||||
|
let fruits = Fruit::find().all(db).await?;
|
||||||
|
|
||||||
|
println!();
|
||||||
|
for ff in fruits.iter() {
|
||||||
|
println!("{:?}\n", ff);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn find_together(db: &DbConn) -> Result<(), DbErr> {
|
||||||
|
print!("find cakes and fruits: ");
|
||||||
|
|
||||||
|
let both = Cake::find().find_also_related(Fruit).all(db).await?;
|
||||||
|
|
||||||
|
println!();
|
||||||
|
for bb in both.iter() {
|
||||||
|
println!("{:?}\n", bb);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Cake {
|
||||||
|
fn find_by_name(name: &str) -> Select<Self> {
|
||||||
|
Self::find().filter(cake::Column::Name.contains(name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn find_one(db: &DbConn) -> Result<(), DbErr> {
|
||||||
|
print!("find one by primary key: ");
|
||||||
|
|
||||||
|
let cheese: Option<cake::Model> = Cake::find_by_id(1).one(db).await?;
|
||||||
|
let cheese = cheese.unwrap();
|
||||||
|
|
||||||
|
println!();
|
||||||
|
println!("{:?}", cheese);
|
||||||
|
println!();
|
||||||
|
|
||||||
|
print!("find one by name: ");
|
||||||
|
|
||||||
|
let chocolate = Cake::find_by_name("chocolate").one(db).await?;
|
||||||
|
|
||||||
|
println!();
|
||||||
|
println!("{:?}", chocolate);
|
||||||
|
println!();
|
||||||
|
|
||||||
|
print!("find models belong to: ");
|
||||||
|
|
||||||
|
let fruits = cheese.find_related(Fruit).all(db).await?;
|
||||||
|
|
||||||
|
println!();
|
||||||
|
for ff in fruits.iter() {
|
||||||
|
println!("{:?}\n", ff);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn count_fruits_by_cake(db: &DbConn) -> Result<(), DbErr> {
|
||||||
|
#[derive(Debug, FromQueryResult)]
|
||||||
|
struct SelectResult {
|
||||||
|
name: String,
|
||||||
|
num_of_fruits: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
print!("count fruits by cake: ");
|
||||||
|
|
||||||
|
let select = Cake::find()
|
||||||
|
.left_join(Fruit)
|
||||||
|
.select_only()
|
||||||
|
.column(cake::Column::Name)
|
||||||
|
.column_as(fruit::Column::Id.count(), "num_of_fruits")
|
||||||
|
.group_by(cake::Column::Name);
|
||||||
|
|
||||||
|
let results = select.into_model::<SelectResult>().all(db).await?;
|
||||||
|
|
||||||
|
println!();
|
||||||
|
for rr in results.iter() {
|
||||||
|
println!("{:?}\n", rr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn find_many_to_many(db: &DbConn) -> Result<(), DbErr> {
|
||||||
|
print!("find cakes and fillings: ");
|
||||||
|
|
||||||
|
let both: Vec<(cake::Model, Vec<filling::Model>)> =
|
||||||
|
Cake::find().find_with_related(Filling).all(db).await?;
|
||||||
|
|
||||||
|
println!();
|
||||||
|
for bb in both.iter() {
|
||||||
|
println!("{:?}\n", bb);
|
||||||
|
}
|
||||||
|
|
||||||
|
print!("find fillings for cheese cake: ");
|
||||||
|
|
||||||
|
let cheese = Cake::find_by_id(1).one(db).await?;
|
||||||
|
|
||||||
|
if let Some(cheese) = cheese {
|
||||||
|
let fillings: Vec<filling::Model> = cheese.find_related(Filling).all(db).await?;
|
||||||
|
|
||||||
|
println!();
|
||||||
|
for ff in fillings.iter() {
|
||||||
|
println!("{:?}\n", ff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
print!("find cakes for lemon: ");
|
||||||
|
|
||||||
|
let lemon = Filling::find_by_id(2).one(db).await?;
|
||||||
|
|
||||||
|
if let Some(lemon) = lemon {
|
||||||
|
let cakes: Vec<cake::Model> = lemon.find_related(Cake).all(db).await?;
|
||||||
|
|
||||||
|
println!();
|
||||||
|
for cc in cakes.iter() {
|
||||||
|
println!("{:?}\n", cc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn all_about_select_json(db: &DbConn) -> Result<(), DbErr> {
|
||||||
|
find_all_json(&db).await?;
|
||||||
|
|
||||||
|
println!("===== =====\n");
|
||||||
|
|
||||||
|
find_together_json(&db).await?;
|
||||||
|
|
||||||
|
println!("===== =====\n");
|
||||||
|
|
||||||
|
count_fruits_by_cake_json(&db).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn find_all_json(db: &DbConn) -> Result<(), DbErr> {
|
||||||
|
print!("find all cakes: ");
|
||||||
|
|
||||||
|
let cakes = Cake::find().into_json().all(db).await?;
|
||||||
|
|
||||||
|
println!("\n{}\n", serde_json::to_string_pretty(&cakes).unwrap());
|
||||||
|
|
||||||
|
print!("find all fruits: ");
|
||||||
|
|
||||||
|
let fruits = Fruit::find().into_json().all(db).await?;
|
||||||
|
|
||||||
|
println!("\n{}\n", serde_json::to_string_pretty(&fruits).unwrap());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn find_together_json(db: &DbConn) -> Result<(), DbErr> {
|
||||||
|
print!("find cakes and fruits: ");
|
||||||
|
|
||||||
|
let cakes_fruits = Cake::find()
|
||||||
|
.find_with_related(Fruit)
|
||||||
|
.into_json()
|
||||||
|
.all(db)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"\n{}\n",
|
||||||
|
serde_json::to_string_pretty(&cakes_fruits).unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn count_fruits_by_cake_json(db: &DbConn) -> Result<(), DbErr> {
|
||||||
|
print!("count fruits by cake: ");
|
||||||
|
|
||||||
|
let count = Cake::find()
|
||||||
|
.left_join(Fruit)
|
||||||
|
.select_only()
|
||||||
|
.column(cake::Column::Name)
|
||||||
|
.column_as(fruit::Column::Id.count(), "num_of_fruits")
|
||||||
|
.group_by(cake::Column::Name)
|
||||||
|
.into_json()
|
||||||
|
.all(db)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
println!("\n{}\n", serde_json::to_string_pretty(&count).unwrap());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn find_all_stream(db: &DbConn) -> Result<(), DbErr> {
|
||||||
|
use async_std::task::sleep;
|
||||||
|
use futures::TryStreamExt;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
println!("find all cakes: ");
|
||||||
|
let mut cake_paginator = cake::Entity::find().paginate(db, 2);
|
||||||
|
while let Some(cake_res) = cake_paginator.fetch_and_next().await? {
|
||||||
|
for cake in cake_res {
|
||||||
|
println!("{:?}", cake);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!();
|
||||||
|
println!("find all fruits: ");
|
||||||
|
let mut fruit_paginator = fruit::Entity::find().paginate(db, 2);
|
||||||
|
while let Some(fruit_res) = fruit_paginator.fetch_and_next().await? {
|
||||||
|
for fruit in fruit_res {
|
||||||
|
println!("{:?}", fruit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!();
|
||||||
|
println!("find all fruits with stream: ");
|
||||||
|
let mut fruit_stream = fruit::Entity::find().paginate(db, 2).into_stream();
|
||||||
|
while let Some(fruits) = fruit_stream.try_next().await? {
|
||||||
|
for fruit in fruits {
|
||||||
|
println!("{:?}", fruit);
|
||||||
|
}
|
||||||
|
sleep(Duration::from_millis(250)).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
println!();
|
||||||
|
println!("find all fruits in json with stream: ");
|
||||||
|
let mut json_stream = fruit::Entity::find()
|
||||||
|
.into_json()
|
||||||
|
.paginate(db, 2)
|
||||||
|
.into_stream();
|
||||||
|
while let Some(jsons) = json_stream.try_next().await? {
|
||||||
|
for json in jsons {
|
||||||
|
println!("{:?}", json);
|
||||||
|
}
|
||||||
|
sleep(Duration::from_millis(250)).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn find_first_page(db: &DbConn) -> Result<(), DbErr> {
|
||||||
|
println!("fruits first page: ");
|
||||||
|
let page = fruit::Entity::find().paginate(db, 2).fetch_page(0).await?;
|
||||||
|
for fruit in page {
|
||||||
|
println!("{:?}", fruit);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn find_num_pages(db: &DbConn) -> Result<(), DbErr> {
|
||||||
|
println!("fruits number of page: ");
|
||||||
|
let num_pages = fruit::Entity::find().paginate(db, 2).num_pages().await?;
|
||||||
|
println!("{:?}", num_pages);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user