Vendor dependencies

This commit is contained in:
2026-08-01 16:11:49 +03:00
parent 7f139a0241
commit 6b5e7f0f8b
29706 changed files with 9575646 additions and 0 deletions
@@ -0,0 +1,5 @@
# Schema for SeaORM test suite
![Entity Relation Diagram](bakery_chain_erd.png)
ERD generated by DataGrip.
@@ -0,0 +1,59 @@
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "baker")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub name: String,
pub contact_details: Json,
pub bakery_id: Option<i32>,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
#[sea_orm(
belongs_to = "super::bakery::Entity",
from = "Column::BakeryId",
to = "super::bakery::Column::Id",
on_update = "Cascade",
on_delete = "SetNull"
)]
Bakery,
}
impl Related<super::bakery::Entity> for Entity {
fn to() -> RelationDef {
Relation::Bakery.def()
}
}
impl Related<super::cake::Entity> for Entity {
fn to() -> RelationDef {
super::cakes_bakers::Relation::Cake.def()
}
fn via() -> Option<RelationDef> {
Some(super::cakes_bakers::Relation::Baker.def().rev())
}
}
pub struct BakedForCustomer;
impl Linked for BakedForCustomer {
type FromEntity = Entity;
type ToEntity = super::customer::Entity;
fn link(&self) -> Vec<RelationDef> {
vec![
super::cakes_bakers::Relation::Baker.def().rev(),
super::cakes_bakers::Relation::Cake.def(),
super::lineitem::Relation::Cake.def().rev(),
super::lineitem::Relation::Order.def(),
super::order::Relation::Customer.def(),
]
}
}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,51 @@
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
#[sea_orm(table_name = "bakery")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub name: String,
pub profit_margin: f64,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
#[sea_orm(has_many = "super::baker::Entity")]
Baker,
#[sea_orm(has_many = "super::order::Entity")]
Order,
#[sea_orm(has_many = "super::cake::Entity")]
Cake,
}
impl Related<super::baker::Entity> for Entity {
fn to() -> RelationDef {
Relation::Baker.def()
}
}
impl Related<super::order::Entity> for Entity {
fn to() -> RelationDef {
Relation::Order.def()
}
}
impl Related<super::cake::Entity> for Entity {
fn to() -> RelationDef {
Relation::Cake.def()
}
}
impl ActiveModelBehavior for ActiveModel {}
pub struct ToBaker;
impl Linked for ToBaker {
type FromEntity = Entity;
type ToEntity = super::baker::Entity;
fn link(&self) -> Vec<RelationDef> {
vec![Relation::Baker.def()]
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 129 KiB

@@ -0,0 +1,132 @@
use sea_orm::{ConnectionTrait, entity::prelude::*};
#[sea_orm::compact_model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "cake")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub name: String,
#[sea_orm(column_type = "Decimal(Some((16, 4)))")]
pub price: Decimal,
pub bakery_id: Option<i32>,
pub gluten_free: bool,
pub serial: Uuid,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
#[sea_orm(
belongs_to = "super::bakery::Entity",
from = "Column::BakeryId",
to = "super::bakery::Column::Id",
on_update = "Cascade",
on_delete = "SetNull"
)]
Bakery,
#[sea_orm(has_many = "super::lineitem::Entity")]
Lineitem,
}
impl Related<super::bakery::Entity> for Entity {
fn to() -> RelationDef {
Relation::Bakery.def()
}
}
impl Related<super::baker::Entity> for Entity {
fn to() -> RelationDef {
super::cakes_bakers::Relation::Baker.def()
}
fn via() -> Option<RelationDef> {
Some(super::cakes_bakers::Relation::Cake.def().rev())
}
}
impl Related<super::lineitem::Entity> for Entity {
fn to() -> RelationDef {
Relation::Lineitem.def()
}
}
pub struct ToBakery;
impl Linked for ToBakery {
type FromEntity = super::cake::Entity;
type ToEntity = super::bakery::Entity;
fn link(&self) -> Vec<RelationDef> {
vec![Relation::Bakery.def()]
}
}
#[async_trait::async_trait]
impl ActiveModelBehavior for ActiveModel {
fn new() -> Self {
use sea_orm::Set;
Self {
serial: Set(Uuid::new_v4()),
..ActiveModelTrait::default()
}
}
async fn before_save<C>(self, _db: &C, insert: bool) -> Result<Self, DbErr>
where
C: ConnectionTrait,
{
if self.price.as_ref() == &Decimal::ZERO {
Err(DbErr::Custom(format!(
"[before_save] Invalid Price, insert: {insert}"
)))
} else {
Ok(self)
}
}
async fn after_save<C>(model: Model, _db: &C, insert: bool) -> Result<Model, DbErr>
where
C: ConnectionTrait,
{
if model.price < Decimal::ZERO {
Err(DbErr::Custom(format!(
"[after_save] Invalid Price, insert: {insert}"
)))
} else {
Ok(model)
}
}
async fn before_delete<C>(self, _db: &C) -> Result<Self, DbErr>
where
C: ConnectionTrait,
{
if self.name.as_ref().contains("(err_on_before_delete)") {
Err(DbErr::Custom(
"[before_delete] Cannot be deleted".to_owned(),
))
} else {
Ok(self)
}
}
async fn after_delete<C>(self, _db: &C) -> Result<Self, DbErr>
where
C: ConnectionTrait,
{
if self.name.as_ref().contains("(err_on_after_delete)") {
Err(DbErr::Custom("[after_delete] Cannot be deleted".to_owned()))
} else {
Ok(self)
}
}
}
#[test]
fn column_type_test() {
let _id: sea_orm::NumericColumn<Entity> = COLUMN.id;
let _name: sea_orm::StringColumn<Entity> = COLUMN.name;
let _price: sea_orm::NumericColumn<Entity> = COLUMN.price;
let _bakery_id: sea_orm::NumericColumnNullable<Entity> = COLUMN.bakery_id;
let _gluten_free: sea_orm::BoolColumn<Entity> = COLUMN.gluten_free;
let _serial: sea_orm::UuidColumn<Entity> = COLUMN.serial;
}
@@ -0,0 +1,30 @@
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "cakes_bakers")]
pub struct Model {
#[sea_orm(primary_key)]
pub cake_id: i32,
#[sea_orm(primary_key)]
pub baker_id: i32,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
#[sea_orm(
belongs_to = "super::cake::Entity",
from = "Column::CakeId",
to = "super::cake::Column::Id",
on_update = "Cascade",
on_delete = "Cascade"
)]
Cake,
#[sea_orm(
belongs_to = "super::baker::Entity",
from = "Column::BakerId",
to = "super::baker::Column::Id"
)]
Baker,
}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,25 @@
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "customer")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub name: String,
#[sea_orm(column_type = "Text", nullable)]
pub notes: Option<String>,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
#[sea_orm(has_many = "super::order::Entity")]
Order,
}
impl Related<super::order::Entity> for Entity {
fn to() -> RelationDef {
Relation::Order.def()
}
}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,47 @@
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "lineitem")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
#[sea_orm(column_type = "Decimal(Some((16, 4)))")]
pub price: Decimal,
pub quantity: i32,
#[sea_orm(unique_key = "lineitem")]
pub order_id: i32,
#[sea_orm(unique_key = "lineitem")]
pub cake_id: i32,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
#[sea_orm(
belongs_to = "super::order::Entity",
from = "Column::OrderId",
to = "super::order::Column::Id",
on_update = "Cascade",
on_delete = "Cascade"
)]
Order,
#[sea_orm(
belongs_to = "super::cake::Entity",
from = "Column::CakeId",
to = "super::cake::Column::Id"
)]
Cake,
}
impl Related<super::order::Entity> for Entity {
fn to() -> RelationDef {
Relation::Order.def()
}
}
impl Related<super::cake::Entity> for Entity {
fn to() -> RelationDef {
Relation::Cake.def()
}
}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,18 @@
pub mod baker;
pub mod bakery;
pub mod cake;
pub mod cakes_bakers;
pub mod customer;
pub mod lineitem;
pub mod order;
pub mod schema;
pub mod seed_data;
pub use baker::Entity as Baker;
pub use bakery::Entity as Bakery;
pub use cake::Entity as Cake;
pub use cakes_bakers::Entity as CakesBakers;
pub use customer::Entity as Customer;
pub use lineitem::Entity as Lineitem;
pub use order::Entity as Order;
pub use schema::*;
@@ -0,0 +1,73 @@
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "order")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
#[sea_orm(column_type = "Decimal(Some((16, 4)))")]
pub total: Decimal,
pub bakery_id: i32,
pub customer_id: i32,
pub placed_at: DateTimeUtc,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
#[sea_orm(
belongs_to = "super::bakery::Entity",
from = "Column::BakeryId",
to = "super::bakery::Column::Id"
)]
Bakery,
#[sea_orm(
belongs_to = "super::customer::Entity",
from = "Column::CustomerId",
to = "super::customer::Column::Id",
on_update = "Cascade",
on_delete = "Cascade"
)]
Customer,
#[sea_orm(has_many = "super::lineitem::Entity")]
Lineitem,
}
impl Related<super::bakery::Entity> for Entity {
fn to() -> RelationDef {
Relation::Bakery.def()
}
}
impl Related<super::customer::Entity> for Entity {
fn to() -> RelationDef {
Relation::Customer.def()
}
}
impl Related<super::lineitem::Entity> for Entity {
fn to() -> RelationDef {
Relation::Lineitem.def()
}
}
pub struct ToCustomer;
impl Linked for ToCustomer {
type FromEntity = Entity;
type ToEntity = super::customer::Entity;
fn link(&self) -> Vec<RelationDef> {
vec![Relation::Customer.def()]
}
}
pub struct ToLineitem;
impl Linked for ToLineitem {
type FromEntity = Entity;
type ToEntity = super::lineitem::Entity;
fn link(&self) -> Vec<RelationDef> {
vec![Relation::Lineitem.def()]
}
}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,268 @@
use super::*;
use crate::common::setup::{create_table, create_table_with_index};
use sea_orm::{
ConnectionTrait, DatabaseConnection, DbConn, ExecResult, Schema, error::*, sea_query,
};
use sea_query::{ColumnDef, ForeignKey, ForeignKeyAction, Index, Table};
pub async fn create_tables(db: &DatabaseConnection) -> Result<(), DbErr> {
create_bakery_table(db).await?;
create_baker_table(db).await?;
create_customer_table(db).await?;
create_order_table(db).await?;
create_cake_table(db).await?;
create_cakes_bakers_table(db).await?;
create_lineitem_table(db).await?;
Ok(())
}
pub async fn create_bakery_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let stmt = Table::create()
.table(bakery::Entity)
.col(
ColumnDef::new(bakery::Column::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(bakery::Column::Name).string().not_null())
.col(
ColumnDef::new(bakery::Column::ProfitMargin)
.double()
.not_null(),
)
.to_owned();
create_table(db, &stmt, Bakery).await
}
pub async fn create_baker_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let stmt = Table::create()
.table(baker::Entity)
.col(
ColumnDef::new(baker::Column::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(baker::Column::Name).string().not_null())
.col(
ColumnDef::new(baker::Column::ContactDetails)
.json()
.not_null(),
)
.col(ColumnDef::new(baker::Column::BakeryId).integer())
.foreign_key(
ForeignKey::create()
.name("fk-baker-bakery_id")
.from(baker::Entity, baker::Column::BakeryId)
.to(bakery::Entity, bakery::Column::Id)
.on_delete(ForeignKeyAction::SetNull)
.on_update(ForeignKeyAction::Cascade),
)
.to_owned();
create_table(db, &stmt, Baker).await
}
pub async fn create_customer_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let stmt = Table::create()
.table(customer::Entity)
.col(
ColumnDef::new(customer::Column::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(customer::Column::Name).string().not_null())
.col(ColumnDef::new(customer::Column::Notes).text())
.to_owned();
create_table(db, &stmt, Customer).await
}
pub async fn create_order_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let stmt = Table::create()
.table(order::Entity)
.col(
ColumnDef::new(order::Column::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(
ColumnDef::new(order::Column::Total)
.decimal_len(16, 4)
.not_null(),
)
.col(ColumnDef::new(order::Column::BakeryId).integer().not_null())
.col(
ColumnDef::new(order::Column::CustomerId)
.integer()
.not_null(),
)
.col(
ColumnDef::new(order::Column::PlacedAt)
.timestamp_with_time_zone()
.not_null(),
)
.foreign_key(
ForeignKey::create()
.name("fk-order-bakery_id")
.from(order::Entity, order::Column::BakeryId)
.to(bakery::Entity, bakery::Column::Id),
)
.foreign_key(
ForeignKey::create()
.name("fk-order-customer_id")
.from(order::Entity, order::Column::CustomerId)
.to(customer::Entity, customer::Column::Id)
.on_delete(ForeignKeyAction::Cascade)
.on_update(ForeignKeyAction::Cascade),
)
.to_owned();
create_table(db, &stmt, Order).await
}
pub async fn create_lineitem_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let stmt = Table::create()
.table(lineitem::Entity)
.col(
ColumnDef::new(lineitem::Column::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(
ColumnDef::new(lineitem::Column::Price)
.decimal_len(16, 4)
.not_null(),
)
.col(
ColumnDef::new(lineitem::Column::Quantity)
.integer()
.not_null(),
)
.col(
ColumnDef::new(lineitem::Column::OrderId)
.integer()
.not_null(),
)
.col(
ColumnDef::new(lineitem::Column::CakeId)
.integer()
.not_null(),
)
.foreign_key(
ForeignKey::create()
.name("fk-lineitem-order_id")
.from(lineitem::Entity, lineitem::Column::OrderId)
.to(order::Entity, order::Column::Id)
.on_delete(ForeignKeyAction::Cascade)
.on_update(ForeignKeyAction::Cascade),
)
.foreign_key(
ForeignKey::create()
.name("fk-lineitem-cake_id")
.from(lineitem::Entity, lineitem::Column::CakeId)
.to(cake::Entity, cake::Column::Id),
)
.to_owned();
let backend = db.get_database_backend();
let stmts = Schema::new(backend).create_index_from_entity(lineitem::Entity);
assert_eq!(stmts.len(), 1);
assert_eq!(
backend.build(&stmts[0]),
backend.build(
Index::create()
.name("idx-lineitem-lineitem")
.table(lineitem::Entity)
.col(lineitem::Column::OrderId)
.col(lineitem::Column::CakeId)
.unique()
)
);
create_table_with_index(db, &stmt, Lineitem).await
}
pub async fn create_cakes_bakers_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let stmt = Table::create()
.table(cakes_bakers::Entity)
.col(
ColumnDef::new(cakes_bakers::Column::CakeId)
.integer()
.not_null(),
)
.col(
ColumnDef::new(cakes_bakers::Column::BakerId)
.integer()
.not_null(),
)
.primary_key(
Index::create()
.name("pk-cakes_bakers")
.col(cakes_bakers::Column::CakeId)
.col(cakes_bakers::Column::BakerId),
)
.foreign_key(
ForeignKey::create()
.name("fk-cakes_bakers-cake_id")
.from(cakes_bakers::Entity, cakes_bakers::Column::CakeId)
.to(cake::Entity, cake::Column::Id)
.on_delete(ForeignKeyAction::Cascade)
.on_update(ForeignKeyAction::Cascade),
)
.foreign_key(
ForeignKey::create()
.name("fk-cakes_bakers-baker_id")
.from(cakes_bakers::Entity, cakes_bakers::Column::BakerId)
.to(baker::Entity, baker::Column::Id),
)
.to_owned();
create_table(db, &stmt, CakesBakers).await
}
pub async fn create_cake_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let stmt = Table::create()
.table(cake::Entity)
.col(
ColumnDef::new(cake::Column::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(cake::Column::Name).string().not_null())
.col(
ColumnDef::new(cake::Column::Price)
.decimal_len(16, 4)
.not_null(),
)
.col(ColumnDef::new(cake::Column::BakeryId).integer())
.foreign_key(
ForeignKey::create()
.name("fk-cake-bakery_id")
.from(cake::Entity, cake::Column::BakeryId)
.to(bakery::Entity, bakery::Column::Id)
.on_delete(ForeignKeyAction::SetNull)
.on_update(ForeignKeyAction::Cascade),
)
.col(
ColumnDef::new(cake::Column::GlutenFree)
.boolean()
.not_null(),
)
.col(ColumnDef::new(cake::Column::Serial).uuid().not_null())
.to_owned();
create_table(db, &stmt, Cake).await
}
@@ -0,0 +1,250 @@
use super::*;
use crate::common::TestContext;
use sea_orm::{NotSet, Set, prelude::*};
pub async fn init_1(ctx: &TestContext, link: bool) {
bakery::Entity::insert(bakery::ActiveModel {
id: Set(42),
name: Set("cool little bakery".to_string()),
profit_margin: Set(4.1),
})
.exec(&ctx.db)
.await
.expect("insert succeeds");
cake::Entity::insert(cake::ActiveModel {
id: Set(13),
name: Set("Cheesecake".to_owned()),
price: Set(2.into()),
bakery_id: Set(if link { Some(42) } else { None }),
gluten_free: Set(false),
..Default::default()
})
.exec(&ctx.db)
.await
.expect("insert succeeds");
cake::Entity::insert(cake::ActiveModel {
id: Set(15),
name: Set("Chocolate".to_owned()),
price: Set(3.into()),
bakery_id: Set(if link { Some(42) } else { None }),
gluten_free: Set(true),
..Default::default()
})
.exec(&ctx.db)
.await
.expect("insert succeeds");
baker::Entity::insert(baker::ActiveModel {
id: Set(22),
name: Set("Master Baker".to_owned()),
contact_details: Set(Json::Null),
bakery_id: Set(if link { Some(42) } else { None }),
})
.exec(&ctx.db)
.await
.expect("insert succeeds");
if link {
cakes_bakers::Entity::insert(cakes_bakers::ActiveModel {
cake_id: Set(13),
baker_id: Set(22),
})
.exec(&ctx.db)
.await
.expect("insert succeeds");
customer::Entity::insert(customer::ActiveModel {
id: Set(11),
name: Set("Bob".to_owned()),
notes: Set(Some("Sweet tooth".to_owned())),
})
.exec(&ctx.db)
.await
.expect("insert succeeds");
order::Entity::insert(order::ActiveModel {
id: Set(101),
total: Set(10.into()),
bakery_id: Set(42),
customer_id: Set(11),
placed_at: Set("2020-01-01T00:00:00Z".parse().unwrap()),
})
.exec(&ctx.db)
.await
.expect("insert succeeds");
lineitem::Entity::insert(lineitem::ActiveModel {
id: NotSet,
price: Set(2.into()),
quantity: Set(2),
order_id: Set(101),
cake_id: Set(13),
})
.exec(&ctx.db)
.await
.expect("insert succeeds");
lineitem::Entity::insert(lineitem::ActiveModel {
id: NotSet,
price: Set(3.into()),
quantity: Set(2),
order_id: Set(101),
cake_id: Set(15),
})
.exec(&ctx.db)
.await
.expect("insert succeeds");
}
}
pub async fn init_2(ctx: &TestContext) -> Result<(), DbErr> {
let db = &ctx.db;
let bakery = bakery::ActiveModel {
name: Set("SeaSide Bakery".to_owned()),
profit_margin: Set(10.4),
..Default::default()
};
let sea = Bakery::insert(bakery).exec(db).await?.last_insert_id;
let bakery = bakery::ActiveModel {
name: Set("LakeSide Bakery".to_owned()),
profit_margin: Set(5.8),
..Default::default()
};
let lake = Bakery::insert(bakery).exec(db).await?.last_insert_id;
let alice = baker::ActiveModel {
name: Set("Alice".to_owned()),
contact_details: Set("+44 15273388".into()),
bakery_id: Set(Some(sea)),
..Default::default()
};
let alice = Baker::insert(alice).exec(db).await?.last_insert_id;
let bob = baker::ActiveModel {
name: Set("Bob".to_owned()),
contact_details: Set("+852 12345678".into()),
bakery_id: Set(Some(lake)),
..Default::default()
};
let bob = Baker::insert(bob).exec(db).await?.last_insert_id;
let cake = cake::ActiveModel {
name: Set("Chocolate Cake".to_owned()),
price: Set("10.25".parse().unwrap()),
gluten_free: Set(false),
bakery_id: Set(Some(sea)),
..Default::default()
};
let choco = Cake::insert(cake).exec(db).await?.last_insert_id;
let cake = cake::ActiveModel {
name: Set("Double Chocolate".to_owned()),
price: Set("12.5".parse().unwrap()),
gluten_free: Set(false),
bakery_id: Set(Some(sea)),
..Default::default()
};
let double_1 = Cake::insert(cake.clone()).exec(db).await?.last_insert_id;
let mut cake = cake::ActiveModel {
name: Set("Lemon Cake".to_owned()),
price: Set("8.8".parse().unwrap()),
gluten_free: Set(true),
bakery_id: Set(Some(sea)),
..Default::default()
};
let lemon_1 = Cake::insert(cake.clone()).exec(db).await?.last_insert_id;
cake.bakery_id = Set(Some(lake));
let _lemon_2 = Cake::insert(cake).exec(db).await?.last_insert_id;
let cake = cake::ActiveModel {
name: Set("Strawberry Cake".to_owned()),
price: Set("9.9".parse().unwrap()),
gluten_free: Set(false),
bakery_id: Set(Some(lake)),
..Default::default()
};
let straw_2 = Cake::insert(cake).exec(db).await?.last_insert_id;
let cake = cake::ActiveModel {
name: Set("Orange Cake".to_owned()),
price: Set("6.5".parse().unwrap()),
gluten_free: Set(true),
bakery_id: Set(Some(lake)),
..Default::default()
};
let orange = Cake::insert(cake).exec(db).await?.last_insert_id;
let mut cake = cake::ActiveModel {
name: Set("New York Cheese".to_owned()),
price: Set("12.5".parse().unwrap()),
gluten_free: Set(false),
bakery_id: Set(Some(sea)),
..Default::default()
};
let cheese_1 = Cake::insert(cake.clone()).exec(db).await?.last_insert_id;
cake.bakery_id = Set(Some(lake));
let cheese_2 = Cake::insert(cake).exec(db).await?.last_insert_id;
let rel = cakes_bakers::ActiveModel {
cake_id: Set(choco),
baker_id: Set(alice),
};
CakesBakers::insert(rel).exec(db).await?;
let rel = cakes_bakers::ActiveModel {
cake_id: Set(double_1),
baker_id: Set(alice),
};
CakesBakers::insert(rel).exec(db).await?;
let rel = cakes_bakers::ActiveModel {
cake_id: Set(lemon_1),
baker_id: Set(alice),
};
CakesBakers::insert(rel).exec(db).await?;
let rel = cakes_bakers::ActiveModel {
cake_id: Set(lemon_1),
baker_id: Set(bob),
};
CakesBakers::insert(rel).exec(db).await?;
let rel = cakes_bakers::ActiveModel {
cake_id: Set(straw_2),
baker_id: Set(bob),
};
CakesBakers::insert(rel).exec(db).await?;
let rel = cakes_bakers::ActiveModel {
cake_id: Set(orange),
baker_id: Set(bob),
};
CakesBakers::insert(rel).exec(db).await?;
let rel = cakes_bakers::ActiveModel {
cake_id: Set(cheese_1),
baker_id: Set(alice),
};
CakesBakers::insert(rel).exec(db).await?;
let rel = cakes_bakers::ActiveModel {
cake_id: Set(cheese_1),
baker_id: Set(bob),
};
CakesBakers::insert(rel).exec(db).await?;
let rel = cakes_bakers::ActiveModel {
cake_id: Set(cheese_2),
baker_id: Set(alice),
};
CakesBakers::insert(rel).exec(db).await?;
let rel = cakes_bakers::ActiveModel {
cake_id: Set(cheese_2),
baker_id: Set(bob),
};
CakesBakers::insert(rel).exec(db).await?;
Ok(())
}
@@ -0,0 +1,4 @@
To regenerate entities, run at project root:
```sh
DATABASE_URL="postgres://sea:sea@localhost/bakery_chain_schema_crud_tests" cargo run --manifest-path sea-orm-cli/Cargo.toml -- generate entity -o tests/common/bakery_dense --entity-format dense --er-diagram
```
@@ -0,0 +1,26 @@
//! `SeaORM` Entity, @generated by sea-orm-codegen 2.0.0-rc.9
use sea_orm::entity::prelude::*;
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "baker")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub name: String,
pub contact_details: Json,
pub bakery_id: Option<i32>,
#[sea_orm(
belongs_to,
from = "bakery_id",
to = "id",
on_update = "Cascade",
on_delete = "SetNull"
)]
pub bakery: BelongsTo<Option<super::bakery::Entity>>,
#[sea_orm(has_many, via = "cakes_bakers::Baker")]
pub cakes: HasMany<super::cake::Entity>,
}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,22 @@
//! `SeaORM` Entity, @generated by sea-orm-codegen 2.0.0-rc.9
use sea_orm::entity::prelude::*;
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
#[sea_orm(table_name = "bakery")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub name: String,
#[sea_orm(column_type = "Double")]
pub profit_margin: f64,
#[sea_orm(has_many)]
pub bakers: HasMany<super::baker::Entity>,
#[sea_orm(has_many)]
pub cakes: HasMany<super::cake::Entity>,
#[sea_orm(has_many)]
pub orders: HasMany<super::order::Entity>,
}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,136 @@
//! `SeaORM` Entity, @generated by sea-orm-codegen 2.0.0-rc.9
use sea_orm::entity::prelude::*;
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "cake")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
#[sea_orm(unique)]
pub name: String,
#[sea_orm(column_type = "Decimal(Some((16, 4)))")]
pub price: Decimal,
pub bakery_id: Option<i32>,
pub gluten_free: bool,
pub serial: Uuid,
#[sea_orm(belongs_to, from = "BakeryId", to = "Id")]
pub bakery: BelongsTo<Option<super::bakery::Entity>>,
#[sea_orm(has_many)]
pub lineitems: HasMany<super::lineitem::Entity>,
#[sea_orm(has_many, via = "cakes_bakers")]
pub bakers: HasMany<super::baker::Entity>,
}
impl ActiveModelBehavior for ActiveModel {
fn new() -> Self {
use sea_orm::Set;
Self {
serial: Set(Uuid::new_v4()),
..ActiveModelTrait::default()
}
}
}
/* // Following will be generated
pub struct EntityLoader {
select: sea_orm::Select<Entity>,
with: EntityLoaderWith,
}
#[derive(Debug, Default)]
struct EntityLoaderWith {
bakery: bool,
baker: bool,
}
impl sea_orm::QueryFilter for EntityLoader {
type QueryStatement = <sea_orm::Select<Entity> as sea_orm::QueryFilter>::QueryStatement;
fn query(&mut self) -> &mut Self::QueryStatement {
sea_orm::QueryFilter::query(&mut self.select)
}
}
impl sea_orm::QueryOrder for EntityLoader {
type QueryStatement = <sea_orm::Select<Entity> as sea_orm::QueryOrder>::QueryStatement;
fn query(&mut self) -> &mut Self::QueryStatement {
sea_orm::QueryOrder::query(&mut self.select)
}
}
impl sea_orm::compound::EntityLoaderTrait<Entity> for EntityLoader {}
impl Entity {
pub fn load() -> EntityLoader {
EntityLoader {
select: Entity::find(),
with: Default::default(),
}
}
}
impl EntityLoader {
pub async fn one<C: sea_orm::ConnectionTrait>(
mut self,
db: &C,
) -> Result<Option<Model>, DbErr> {
use sea_orm::QuerySelect;
self.select = self.select.limit(1);
Ok(self.all(db).await?.into_iter().next())
}
pub fn with<R>(mut self, entity: R) -> Self
where
R: EntityTrait,
Entity: Related<R>,
{
if entity.table_ref() == super::bakery::Entity.table_ref() {
self.with.bakery = true;
}
if entity.table_ref() == super::baker::Entity.table_ref() {
self.with.baker = true;
}
self
}
pub async fn load<C: sea_orm::ConnectionTrait>(Vec<Model>, with: &EntityLoaderWith, nest: &EntityLoaderNest, db: &C) -> Result<Vec<Model>, DbErr> {
if self.with.baker {
let bakers = cakes.load_many(super::baker::Entity, db).await?;
super::baker::EntityLoader::load_nest_nest(bakers, &nest.baker).await?;
for (cake, bakers) in cakes.iter_mut().zip(bakers) {
cake.bakers.set(bakers);
}
}
}
pub async fn all<C: sea_orm::ConnectionTrait>(mut self, db: &C) -> Result<Vec<Model>, DbErr> {
let select = if self.with.bakery {
self.with.bakery = false;
self.select.find_also(Entity, super::bakery::Entity)
} else {
// select also but without join
self.select.select_also_fake(super::bakery::Entity)
};
let models = select.all(db).await?;
let mut cakes = Vec::new();
for (mut cake, bakery) in models {
cake.bakery.set(bakery);
cakes.push(cake);
}
let cakes = Self::load(cakes, &self.with, db).await?;
Ok(cakes)
}
}
*/
@@ -0,0 +1,19 @@
//! `SeaORM` Entity, @generated by sea-orm-codegen 2.0.0-rc.9
use sea_orm::entity::prelude::*;
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "cakes_bakers")]
pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub cake_id: i32,
#[sea_orm(primary_key, auto_increment = false)]
pub baker_id: i32,
#[sea_orm(belongs_to, from = "baker_id", to = "id")]
pub baker: BelongsTo<super::baker::Entity>,
#[sea_orm(belongs_to, from = "cake_id", to = "id")]
pub cake: BelongsTo<super::cake::Entity>,
}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,18 @@
//! `SeaORM` Entity, @generated by sea-orm-codegen 2.0.0-rc.9
use sea_orm::entity::prelude::*;
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "customer")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub name: String,
#[sea_orm(column_type = "Text", nullable)]
pub notes: Option<String>,
#[sea_orm(has_many)]
pub orders: HasMany<super::order::Entity>,
}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,52 @@
erDiagram
baker {
int id PK
varchar name
json contact_details
int bakery_id FK
}
bakery {
int id PK
varchar name
double profit_margin
}
cake {
int id PK
varchar name
decimal price
int bakery_id FK
bool gluten_free
uuid serial
}
cakes_bakers {
int cake_id PK,FK
int baker_id PK,FK
}
customer {
int id PK
varchar name
text notes
}
lineitem {
int id PK
decimal price
int quantity
int order_id FK,UK
int cake_id FK,UK
}
order {
int id PK
decimal total
int bakery_id FK
int customer_id FK
timestamptz placed_at
}
baker }o--|| bakery : "bakery_id"
baker }o--o{ cake : "[cakes_bakers]"
cake }o--|| bakery : "bakery_id"
cakes_bakers }o--|| baker : "baker_id"
cakes_bakers }o--|| cake : "cake_id"
lineitem }o--|| cake : "cake_id"
lineitem }o--|| order : "order_id"
order }o--|| bakery : "bakery_id"
order }o--|| customer : "customer_id"
@@ -0,0 +1,50 @@
//! `SeaORM` Entity, @generated by sea-orm-codegen 2.0.0-rc.9
use sea_orm::entity::prelude::*;
#[sea_orm::compact_model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "lineitem")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
#[sea_orm(column_type = "Decimal(Some((16, 4)))")]
pub price: Decimal,
pub quantity: i32,
pub order_id: i32,
pub cake_id: i32,
pub order: BelongsTo<super::order::Entity>,
pub cake: BelongsTo<super::cake::Entity>,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
#[sea_orm(
belongs_to = "super::order::Entity",
from = "Column::OrderId",
to = "super::order::Column::Id",
on_update = "Cascade",
on_delete = "Cascade"
)]
Order,
#[sea_orm(
belongs_to = "super::cake::Entity",
from = "Column::CakeId",
to = "super::cake::Column::Id"
)]
Cake,
}
impl Related<super::order::Entity> for Entity {
fn to() -> RelationDef {
Relation::Order.def()
}
}
impl Related<super::cake::Entity> for Entity {
fn to() -> RelationDef {
Relation::Cake.def()
}
}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,12 @@
//! `SeaORM` Entity, @generated by sea-orm-codegen 2.0.0-rc.9
// DATABASE_URL=sqlite://bakery.db cargo run --manifest-path sea-orm-cli/Cargo.toml -- generate entity --output-dir tests/common/bakery_dense --entity-format dense
pub mod prelude;
pub mod baker;
pub mod bakery;
pub mod cake;
pub mod cakes_bakers;
pub mod customer;
pub mod lineitem;
pub mod order;
@@ -0,0 +1,24 @@
//! `SeaORM` Entity, @generated by sea-orm-codegen 2.0.0-rc.9
use sea_orm::entity::prelude::*;
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "order")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
#[sea_orm(column_type = "Decimal(Some((16, 4)))")]
pub total: Decimal,
pub bakery_id: i32,
pub customer_id: i32,
pub placed_at: DateTimeWithTimeZone,
#[sea_orm(belongs_to, from = "bakery_id", to = "id")]
pub bakery: BelongsTo<super::bakery::Entity>,
#[sea_orm(belongs_to, from = "customer_id", to = "id")]
pub customer: BelongsTo<super::customer::Entity>,
#[sea_orm(has_many)]
pub lineitems: HasMany<super::lineitem::Entity>,
}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,9 @@
//! `SeaORM` Entity, @generated by sea-orm-codegen 2.0.0-rc.16
pub use super::baker::Entity as Baker;
pub use super::bakery::Entity as Bakery;
pub use super::cake::Entity as Cake;
pub use super::cakes_bakers::Entity as CakesBakers;
pub use super::customer::Entity as Customer;
pub use super::lineitem::Entity as Lineitem;
pub use super::order::Entity as Order;
@@ -0,0 +1,15 @@
use sea_orm::entity::prelude::*;
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "attachment")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub post_id: Option<i32>,
pub file: String,
#[sea_orm(belongs_to, from = "post_id", to = "id")]
pub post: BelongsTo<Option<super::post::Entity>>,
}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,18 @@
use sea_orm::entity::prelude::*;
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "comment")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub comment: String,
pub user_id: i32,
pub post_id: i32,
#[sea_orm(belongs_to, from = "user_id", to = "id")]
pub user: BelongsTo<super::user::Entity>,
#[sea_orm(belongs_to, from = "post_id", to = "id")]
pub post: BelongsTo<super::post::Entity>,
}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,9 @@
pub mod attachment;
pub mod comment;
pub mod post;
pub mod post_tag;
pub mod profile;
pub mod tag;
pub mod user;
pub mod user_follower;
pub mod user_mono;
@@ -0,0 +1,21 @@
use sea_orm::entity::prelude::*;
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "post")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub user_id: i32,
pub title: String,
#[sea_orm(belongs_to, from = "user_id", to = "id")]
pub author: BelongsTo<super::user::Entity>,
#[sea_orm(has_many)]
pub comments: HasMany<super::comment::Entity>,
#[sea_orm(has_many)]
pub attachments: HasMany<super::attachment::Entity>,
#[sea_orm(has_many, via = "post_tag")]
pub tags: HasMany<super::tag::Entity>,
}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,17 @@
use sea_orm::entity::prelude::*;
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
#[sea_orm(table_name = "post_tag")]
pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub post_id: i32,
#[sea_orm(primary_key, auto_increment = false)]
pub tag_id: i32,
#[sea_orm(belongs_to, from = "post_id", to = "id")]
pub post: BelongsTo<super::post::Entity>,
#[sea_orm(belongs_to, from = "tag_id", to = "id")]
pub tag: BelongsTo<super::tag::Entity>,
}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,16 @@
use sea_orm::entity::prelude::*;
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "profile")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub picture: String,
#[sea_orm(unique)]
pub user_id: i32,
#[sea_orm(belongs_to, from = "user_id", to = "id")]
pub user: BelongsTo<super::user::Entity>,
}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,14 @@
use sea_orm::entity::prelude::*;
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "tag")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub tag: String,
#[sea_orm(has_many, via = "post_tag")]
pub posts: HasMany<super::post::Entity>,
}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,36 @@
use sea_orm::entity::prelude::*;
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "user")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub name: String,
#[sea_orm(unique)]
pub email: String,
#[sea_orm(has_one)]
pub profile: HasOne<super::profile::Entity>,
#[sea_orm(has_many)]
pub posts: HasMany<super::post::Entity>,
#[sea_orm(self_ref, via = "user_follower", from = "User", to = "Follower")]
pub followers: HasMany<Entity>,
#[sea_orm(self_ref, via = "user_follower", reverse)]
pub following: HasMany<Entity>,
}
impl ActiveModelBehavior for ActiveModel {}
pub use super::user_follower::Entity as Follower;
// the name `EntityReverse` is still subject to change
pub use super::user_follower::EntityReverse as Following;
// the following trait impl will be generated by the marco:
// impl RelatedSelfVia<super::user_follower::Entity> for Entity {
// fn to() -> RelationDef {
// super::user_follower::Relation::Follower.def()
// }
// fn via() -> RelationDef {
// super::user_follower::Relation::User.def().rev()
// }
// }
@@ -0,0 +1,22 @@
use sea_orm::entity::prelude::*;
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
#[sea_orm(table_name = "user_follower")]
pub struct Model {
#[sea_orm(primary_key)]
pub user_id: i32,
#[sea_orm(primary_key)]
pub follower_id: i32,
#[sea_orm(belongs_to, from = "user_id", to = "id")]
pub user: BelongsTo<super::user::Entity>,
#[sea_orm(
belongs_to,
relation_enum = "Follower",
from = "follower_id",
to = "id"
)]
pub follower: BelongsTo<super::user::Entity>,
}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,16 @@
use sea_orm::entity::prelude::*;
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "user")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub name: String,
#[sea_orm(unique)]
pub email: String,
#[sea_orm(self_ref, via = "user_follower", from = "User", to = "Follower")]
pub followers: HasMany<Entity>,
}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,15 @@
use sea_orm::entity::prelude::*;
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "attachment")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub post_id: Option<i32>,
pub file: String,
#[sea_orm(belongs_to, from = "post_id", to = "id")]
pub post: HasOne<super::post::Entity>,
}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,18 @@
use sea_orm::entity::prelude::*;
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "comment")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub comment: String,
pub user_id: i32,
pub post_id: i32,
#[sea_orm(belongs_to, from = "user_id", to = "id")]
pub user: HasOne<super::user::Entity>,
#[sea_orm(belongs_to, from = "post_id", to = "id")]
pub post: HasOne<super::post::Entity>,
}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,9 @@
pub mod attachment;
pub mod comment;
pub mod post;
pub mod post_tag;
pub mod profile;
pub mod tag;
pub mod user;
pub mod user_follower;
pub mod user_mono;
@@ -0,0 +1,21 @@
use sea_orm::entity::prelude::*;
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "post")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub user_id: i32,
pub title: String,
#[sea_orm(belongs_to, from = "user_id", to = "id")]
pub author: HasOne<super::user::Entity>,
#[sea_orm(has_many)]
pub comments: HasMany<super::comment::Entity>,
#[sea_orm(has_many)]
pub attachments: HasMany<super::attachment::Entity>,
#[sea_orm(has_many, via = "post_tag")]
pub tags: HasMany<super::tag::Entity>,
}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,17 @@
use sea_orm::entity::prelude::*;
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
#[sea_orm(table_name = "post_tag")]
pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub post_id: i32,
#[sea_orm(primary_key, auto_increment = false)]
pub tag_id: i32,
#[sea_orm(belongs_to, from = "post_id", to = "id")]
pub post: HasOne<super::post::Entity>,
#[sea_orm(belongs_to, from = "tag_id", to = "id")]
pub tag: HasOne<super::tag::Entity>,
}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,16 @@
use sea_orm::entity::prelude::*;
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "profile")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub picture: String,
#[sea_orm(unique)]
pub user_id: i32,
#[sea_orm(belongs_to, from = "user_id", to = "id")]
pub user: HasOne<super::user::Entity>,
}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,14 @@
use sea_orm::entity::prelude::*;
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "tag")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub tag: String,
#[sea_orm(has_many, via = "post_tag")]
pub posts: HasMany<super::post::Entity>,
}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,36 @@
use sea_orm::entity::prelude::*;
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "user")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub name: String,
#[sea_orm(unique)]
pub email: String,
#[sea_orm(has_one)]
pub profile: HasOne<super::profile::Entity>,
#[sea_orm(has_many)]
pub posts: HasMany<super::post::Entity>,
#[sea_orm(self_ref, via = "user_follower", from = "User", to = "Follower")]
pub followers: HasMany<Entity>,
#[sea_orm(self_ref, via = "user_follower", reverse)]
pub following: HasMany<Entity>,
}
impl ActiveModelBehavior for ActiveModel {}
pub use super::user_follower::Entity as Follower;
// the name `EntityReverse` is still subject to change
pub use super::user_follower::EntityReverse as Following;
// the following trait impl will be generated by the marco:
// impl RelatedSelfVia<super::user_follower::Entity> for Entity {
// fn to() -> RelationDef {
// super::user_follower::Relation::Follower.def()
// }
// fn via() -> RelationDef {
// super::user_follower::Relation::User.def().rev()
// }
// }
@@ -0,0 +1,22 @@
use sea_orm::entity::prelude::*;
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
#[sea_orm(table_name = "user_follower")]
pub struct Model {
#[sea_orm(primary_key)]
pub user_id: i32,
#[sea_orm(primary_key)]
pub follower_id: i32,
#[sea_orm(belongs_to, from = "user_id", to = "id")]
pub user: HasOne<super::user::Entity>,
#[sea_orm(
belongs_to,
relation_enum = "Follower",
from = "follower_id",
to = "id"
)]
pub follower: HasOne<super::user::Entity>,
}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,16 @@
use sea_orm::entity::prelude::*;
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "user")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub name: String,
#[sea_orm(unique)]
pub email: String,
#[sea_orm(self_ref, via = "user_follower", from = "User", to = "Follower")]
pub followers: HasMany<Entity>,
}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,39 @@
use super::sea_orm_active_enums::*;
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[cfg_attr(feature = "sqlx-postgres", sea_orm(schema_name = "public"))]
#[sea_orm(table_name = "active_enum")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub category: Option<Category>,
pub color: Option<Color>,
pub tea: Option<Tea>,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
#[sea_orm(has_many = "super::active_enum_child::Entity")]
ActiveEnumChild,
}
impl Related<super::active_enum_child::Entity> for Entity {
fn to() -> RelationDef {
Relation::ActiveEnumChild.def()
}
}
pub struct ActiveEnumChildLink;
impl Linked for ActiveEnumChildLink {
type FromEntity = Entity;
type ToEntity = super::active_enum_child::Entity;
fn link(&self) -> Vec<RelationDef> {
vec![Relation::ActiveEnumChild.def()]
}
}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,45 @@
use super::sea_orm_active_enums::*;
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[cfg_attr(feature = "sqlx-postgres", sea_orm(schema_name = "public"))]
#[sea_orm(table_name = "active_enum_child")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub parent_id: i32,
pub category: Option<Category>,
pub color: Option<Color>,
pub tea: Option<Tea>,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
#[sea_orm(
fk_name = "fk-active_enum_child-active_enum",
belongs_to = "super::active_enum::Entity",
from = "Column::ParentId",
to = "super::active_enum::Column::Id"
)]
ActiveEnum,
}
impl Related<super::active_enum::Entity> for Entity {
fn to() -> RelationDef {
Relation::ActiveEnum.def()
}
}
pub struct ActiveEnumLink;
impl Linked for ActiveEnumLink {
type FromEntity = Entity;
type ToEntity = super::active_enum::Entity;
fn link(&self) -> Vec<RelationDef> {
vec![Relation::ActiveEnum.def()]
}
}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,16 @@
use super::sea_orm_active_enums::*;
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[cfg_attr(feature = "sqlx-postgres", sea_orm(schema_name = "public"))]
#[sea_orm(table_name = "active_enum")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub categories: Option<Vec<Category>>,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,19 @@
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "applog", comment = "app logs")]
pub struct Model {
#[sea_orm(primary_key, comment = "ID")]
pub id: i32,
#[sea_orm(comment = "action")]
pub action: String,
#[sea_orm(comment = "action data")]
pub json: Json,
#[sea_orm(comment = "create time")]
pub created_at: DateTimeWithTimeZone,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,19 @@
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "binary")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
#[sea_orm(column_type = "Binary(1)")]
pub binary: Vec<u8>,
#[sea_orm(column_type = "Binary(10)")]
pub binary_10: Vec<u8>,
#[sea_orm(column_type = "VarBinary(StringLen::N(16))")]
pub var_binary_16: Vec<u8>,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,49 @@
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "bits")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
#[sea_orm(
column_type = r#"custom("BIT")"#,
select_as = "BIGINT",
save_as = "BIT"
)]
pub bit0: i64,
#[sea_orm(
column_type = r#"custom("BIT(1)")"#,
select_as = "BIGINT",
save_as = "BIT(1)"
)]
pub bit1: i64,
#[sea_orm(
column_type = r#"custom("BIT(8)")"#,
select_as = "BIGINT",
save_as = "BIT(8)"
)]
pub bit8: i64,
#[sea_orm(
column_type = r#"custom("BIT(16)")"#,
select_as = "BIGINT",
save_as = "BIT(16)"
)]
pub bit16: i64,
#[sea_orm(
column_type = r#"custom("BIT(32)")"#,
select_as = "BIGINT",
save_as = "BIT(32)"
)]
pub bit32: i64,
#[sea_orm(
column_type = r#"custom("BIT(64)")"#,
select_as = "BIGINT",
save_as = "BIT(64)"
)]
pub bit64: i64,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,14 @@
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "byte_primary_key")]
pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub id: Vec<u8>,
pub value: String,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,15 @@
use super::sea_orm_active_enums::*;
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "categories")]
pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub id: i32,
pub categories: Option<Vec<Category>>,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,29 @@
use super::sea_orm_active_enums::*;
use sea_orm::entity::prelude::*;
#[sea_orm::compact_model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "collection")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
#[sea_orm(
column_type = r#"custom("citext")"#,
select_as = "text",
save_as = "citext"
)]
pub name: String,
pub integers: Vec<i32>,
pub integers_opt: Option<Vec<i32>>,
pub teas: Vec<Tea>,
pub teas_opt: Option<Vec<Tea>>,
pub colors: Vec<Color>,
pub colors_opt: Option<Vec<Color>>,
pub uuid: Vec<Uuid>,
pub uuid_hyphenated: Vec<uuid::fmt::Hyphenated>,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,64 @@
use sea_orm::entity::prelude::*;
#[derive(Copy, Clone, Default, Debug, DeriveEntity)]
pub struct Entity;
impl EntityName for Entity {
fn schema_name(&self) -> Option<&str> {
Some("schema_name")
}
fn table_name(&self) -> &'static str {
"collection"
}
}
#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel, Eq)]
pub struct Model {
pub id: i32,
pub integers: Vec<i32>,
pub integers_opt: Option<Vec<i32>>,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
pub enum Column {
Id,
Integers,
IntegersOpt,
}
#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
pub enum PrimaryKey {
Id,
}
impl PrimaryKeyTrait for PrimaryKey {
type ValueType = i32;
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::Integers => ColumnType::Array(RcOrArc::new(ColumnType::Integer)).def(),
Self::IntegersOpt => ColumnType::Array(RcOrArc::new(ColumnType::Integer))
.def()
.null(),
}
}
}
impl RelationTrait for Relation {
fn def(&self) -> RelationDef {
panic!("No RelationDef")
}
}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,32 @@
use super::sea_orm_active_enums::*;
use sea_orm::entity::prelude::*;
use sea_orm::{ActiveValue, IntoActiveValue};
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
#[cfg_attr(feature = "sqlx-postgres", sea_orm(schema_name = "public"))]
#[sea_orm(table_name = "custom_active_model")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub age: i32,
pub weight: Option<f32>,
pub amount: Option<i32>,
pub tea: Tea,
pub category: Option<Category>,
pub color: Option<Color>,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
#[derive(Clone, Debug, PartialEq, DeriveIntoActiveModel)]
pub struct CustomActiveModel {
pub age: Option<i32>,
pub weight: Option<f32>,
pub amount: Option<Option<i32>>,
pub tea: Option<Tea>,
pub category: Option<Category>,
pub color: Option<Option<Color>>,
}
@@ -0,0 +1,57 @@
use sea_orm::entity::prelude::*;
#[derive(Copy, Clone, Default, Debug, DeriveEntity)]
pub struct Entity {
pub table_name: u32,
}
impl EntityName for Entity {
fn table_name(&self) -> &'static str {
match self.table_name {
1 => "dyn_table_1",
2 => "dyn_table_2",
_ => "",
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, 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 {
type ValueType = i32;
fn auto_increment() -> bool {
true
}
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
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(StringLen::None).def(),
}
}
}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,15 @@
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "edit_log")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub action: String,
pub values: Json,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,15 @@
use super::sea_orm_active_enums::*;
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
#[sea_orm(table_name = "embedding")]
pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub id: i32,
pub embedding: PgVector,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,63 @@
use sea_orm::entity::prelude::*;
use sea_orm::{
TryGetError, TryGetable,
sea_query::{ArrayType, ColumnType, ValueType},
};
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "event_trigger")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub events: Events,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Event(pub String);
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Events(pub Vec<Event>);
impl From<Events> for Value {
fn from(events: Events) -> Self {
let Events(events) = events;
let vec: Vec<String> = events.into_iter().map(|Event(s)| s).collect();
vec.into()
}
}
impl TryGetable for Events {
fn try_get_by<I: sea_orm::ColIdx>(res: &QueryResult, idx: I) -> Result<Self, TryGetError> {
let vec: Vec<String> = res.try_get_by(idx).map_err(TryGetError::DbErr)?;
Ok(Events(vec.into_iter().map(Event).collect()))
}
}
impl ValueType for Events {
fn try_from(v: Value) -> Result<Self, sea_query::ValueTypeErr> {
let value: Option<Vec<String>> =
v.expect("This Value::Array should consist of Value::String");
let vec = match value {
Some(v) => v.into_iter().map(Event).collect(),
None => vec![],
};
Ok(Events(vec))
}
fn type_name() -> String {
stringify!(Events).to_owned()
}
fn array_type() -> ArrayType {
ArrayType::String
}
fn column_type() -> ColumnType {
ColumnType::Array(RcOrArc::new(ColumnType::String(StringLen::None)))
}
}
@@ -0,0 +1,17 @@
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "host_network")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub hostname: String,
pub ipaddress: IpNetwork,
#[sea_orm(column_type = "Cidr")]
pub network: IpNetwork,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,13 @@
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "insert_default")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,41 @@
use sea_orm::FromJsonQueryResult;
use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize, Serializer};
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
#[sea_orm(table_name = "json_struct")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub json: Json,
pub json_value: KeyValue,
pub json_value_opt: Option<KeyValue>,
pub json_non_serializable: Option<NonSerializableStruct>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, FromJsonQueryResult)]
pub struct KeyValue {
pub id: i32,
pub name: String,
pub price: f32,
pub notes: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Deserialize, FromJsonQueryResult)]
pub struct NonSerializableStruct;
impl Serialize for NonSerializableStruct {
fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
Err(serde::ser::Error::custom(
"intentionally failing serialization",
))
}
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,56 @@
use sea_orm::TryGetableFromJson;
use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "json_vec")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub str_vec: Option<StringVec>,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct StringVec(pub Vec<String>);
impl TryGetableFromJson for StringVec {}
impl From<StringVec> for Value {
fn from(source: StringVec) -> Self {
sea_orm::Value::Json(serde_json::to_value(source).ok().map(std::boxed::Box::new))
}
}
impl sea_query::ValueType for StringVec {
fn try_from(v: Value) -> Result<Self, sea_query::ValueTypeErr> {
match v {
sea_orm::Value::Json(Some(json)) => {
Ok(serde_json::from_value(*json).map_err(|_| sea_orm::sea_query::ValueTypeErr)?)
}
_ => Err(sea_orm::sea_query::ValueTypeErr),
}
}
fn type_name() -> String {
stringify!(StringVec).to_owned()
}
fn array_type() -> sea_orm::sea_query::ArrayType {
sea_orm::sea_query::ArrayType::Json
}
fn column_type() -> sea_query::ColumnType {
sea_query::ColumnType::Json
}
}
impl sea_orm::sea_query::Nullable for StringVec {
fn null() -> sea_orm::Value {
sea_orm::Value::Json(None)
}
}
@@ -0,0 +1,46 @@
pub mod json_string_vec {
use sea_orm::FromJsonQueryResult;
use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "json_string_vec")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub str_vec: Option<StringVec>,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, FromJsonQueryResult)]
pub struct StringVec(pub Vec<String>);
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
}
pub mod json_struct_vec {
use sea_orm::entity::prelude::*;
use sea_orm_macros::FromJsonQueryResult;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "json_struct_vec")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
#[sea_orm(column_type = "JsonBinary")]
pub struct_vec: Vec<JsonColumn>,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, FromJsonQueryResult)]
pub struct JsonColumn {
pub value: String,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
}
@@ -0,0 +1,21 @@
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "metadata")]
pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub uuid: Uuid,
#[sea_orm(column_name = "type", enum_name = "Type")]
pub ty: String,
pub key: String,
pub value: String,
#[sea_orm(column_type = "var_binary(32)")]
pub bytes: Vec<u8>,
pub date: Option<Date>,
pub time: Option<Time>,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,64 @@
pub mod active_enum;
pub mod active_enum_child;
pub mod active_enum_vec;
pub mod applog;
pub mod binary;
pub mod bits;
pub mod byte_primary_key;
pub mod categories;
pub mod collection;
pub mod collection_expanded;
pub mod custom_active_model;
pub mod dyn_table_name;
pub mod edit_log;
#[cfg(feature = "postgres-vector")]
pub mod embedding;
pub mod event_trigger;
#[cfg(feature = "with-ipnetwork")]
pub mod host_network;
pub mod insert_default;
pub mod json_struct;
pub mod json_vec;
pub mod json_vec_derive;
pub mod metadata;
#[cfg(feature = "with-bigdecimal")]
pub mod pi;
pub mod repository;
pub mod satellite;
pub mod schema;
pub mod sea_orm_active_enums;
pub mod self_join;
pub mod teas;
pub mod transaction_log;
pub mod uuid_fmt;
pub mod value_type;
pub use active_enum::Entity as ActiveEnum;
pub use active_enum_child::Entity as ActiveEnumChild;
pub use active_enum_vec::Entity as ActiveEnumVec;
pub use applog::Entity as Applog;
pub use binary::Entity as Binary;
pub use bits::Entity as Bits;
pub use byte_primary_key::Entity as BytePrimaryKey;
pub use categories::Entity as Categories;
pub use collection::Entity as Collection;
pub use collection_expanded::Entity as CollectionExpanded;
pub use dyn_table_name::Entity as DynTableName;
pub use edit_log::Entity as EditLog;
#[cfg(feature = "postgres-vector")]
pub use embedding::Entity as Embedding;
pub use event_trigger::Entity as EventTrigger;
pub use insert_default::Entity as InsertDefault;
pub use json_struct::Entity as JsonStruct;
pub use json_vec::Entity as JsonVec;
pub use json_vec_derive::json_string_vec::Entity as JsonStringVec;
pub use json_vec_derive::json_struct_vec::Entity as JsonStructVec;
pub use metadata::Entity as Metadata;
pub use repository::Entity as Repository;
pub use satellite::Entity as Satellite;
pub use schema::*;
pub use sea_orm_active_enums::*;
pub use self_join::Entity as SelfJoin;
pub use teas::Entity as Teas;
pub use transaction_log::Entity as TransactionLog;
pub use uuid_fmt::Entity as UuidFmt;
@@ -0,0 +1,21 @@
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "pi")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
#[sea_orm(column_type = "Decimal(Some((11, 10)))")]
pub decimal: Decimal,
#[sea_orm(column_type = "Decimal(Some((11, 10)))")]
pub big_decimal: BigDecimal,
#[sea_orm(column_type = "Decimal(Some((11, 10)))")]
pub decimal_opt: Option<Decimal>,
#[sea_orm(column_type = "Decimal(Some((11, 10)))")]
pub big_decimal_opt: Option<BigDecimal>,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,71 @@
use super::edit_log;
use sea_orm::{ConnectionTrait, Set, TryIntoModel, entity::prelude::*};
use serde::Serialize;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel, Serialize)]
#[sea_orm(table_name = "repository")]
pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub id: String,
pub owner: String,
pub name: String,
pub description: Option<String>,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
#[async_trait::async_trait]
impl ActiveModelBehavior for ActiveModel {
async fn before_save<C>(self, db: &C, _: bool) -> Result<Self, DbErr>
where
C: ConnectionTrait,
{
let model = self.clone().try_into_model()?;
insert_edit_log("before_save", &model, db).await?;
Ok(self)
}
async fn after_save<C>(model: Model, db: &C, _: bool) -> Result<Model, DbErr>
where
C: ConnectionTrait,
{
insert_edit_log("after_save", &model, db).await?;
Ok(model)
}
async fn before_delete<C>(self, db: &C) -> Result<Self, DbErr>
where
C: ConnectionTrait,
{
let model = self.clone().try_into_model()?;
insert_edit_log("before_delete", &model, db).await?;
Ok(self)
}
async fn after_delete<C>(self, db: &C) -> Result<Self, DbErr>
where
C: ConnectionTrait,
{
let model = self.clone().try_into_model()?;
insert_edit_log("after_delete", &model, db).await?;
Ok(self)
}
}
async fn insert_edit_log<T, M, C>(action: T, model: &M, db: &C) -> Result<(), DbErr>
where
T: Into<String>,
M: Serialize,
C: ConnectionTrait,
{
edit_log::ActiveModel {
action: Set(action.into()),
values: Set(serde_json::json!(model)),
..Default::default()
}
.insert(db)
.await?;
Ok(())
}
@@ -0,0 +1,18 @@
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "satellite")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub satellite_name: String,
#[sea_orm(default_value = "2022-01-26 16:24:00")]
pub launch_date: DateTimeUtc,
#[sea_orm(default_value = "2022-01-26 16:24:00")]
pub deployment_date: DateTimeLocal,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,806 @@
use super::*;
use crate::common::setup::{
create_enum, create_table, create_table_from_entity, create_table_without_asserts,
};
use sea_orm::{
ConnectionTrait, DatabaseConnection, DbBackend, DbConn, EntityName, ExecResult, Schema,
error::*, sea_query,
};
use sea_query::{
Alias, ColumnDef, ColumnType, ForeignKeyCreateStatement, IntoIden, IntoTableRef, StringLen,
extension::postgres::Type,
};
pub async fn create_tea_enum(db: &DatabaseConnection) -> Result<(), DbErr> {
let db_backend = db.get_database_backend();
let create_enum_stmts = match db_backend {
DbBackend::MySql | DbBackend::Sqlite => Vec::new(),
DbBackend::Postgres => {
let schema = Schema::new(db_backend);
let enum_create_stmt = Type::create()
.as_enum("tea")
.values(["EverydayTea", "BreakfastTea", "AfternoonTea"])
.to_owned();
assert_eq!(
db_backend.build(&enum_create_stmt),
db_backend.build(&schema.create_enum_from_active_enum::<Tea>().unwrap())
);
vec![enum_create_stmt]
}
db => {
return Err(DbErr::BackendNotSupported {
db: db.as_str(),
ctx: "create_tea_enum",
});
}
};
create_enum(db, &create_enum_stmts, ActiveEnum).await?;
Ok(())
}
pub async fn create_log_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let stmt = sea_query::Table::create()
.table(applog::Entity)
.comment("app logs")
.col(
ColumnDef::new(applog::Column::Id)
.integer()
.not_null()
.comment("ID")
.auto_increment()
.primary_key(),
)
.col(
ColumnDef::new(applog::Column::Action)
.string()
.not_null()
.comment("action"),
)
.col(
ColumnDef::new(applog::Column::Json)
.json()
.not_null()
.comment("action data"),
)
.col(
ColumnDef::new(applog::Column::CreatedAt)
.timestamp_with_time_zone()
.not_null()
.comment("create time"),
)
.to_owned();
create_table(db, &stmt, Applog).await
}
pub async fn create_metadata_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let stmt = sea_query::Table::create()
.table(metadata::Entity)
.col(
ColumnDef::new(metadata::Column::Uuid)
.uuid()
.not_null()
.primary_key(),
)
.col(ColumnDef::new(metadata::Column::Type).string().not_null())
.col(ColumnDef::new(metadata::Column::Key).string().not_null())
.col(ColumnDef::new(metadata::Column::Value).string().not_null())
.col(
ColumnDef::new_with_type(
metadata::Column::Bytes,
ColumnType::VarBinary(StringLen::N(32)),
)
.not_null(),
)
.col(ColumnDef::new(metadata::Column::Date).date())
.col(ColumnDef::new(metadata::Column::Time).time())
.to_owned();
create_table(db, &stmt, Metadata).await
}
pub async fn create_repository_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let stmt = sea_query::Table::create()
.table(repository::Entity)
.col(
ColumnDef::new(repository::Column::Id)
.string()
.not_null()
.primary_key(),
)
.col(
ColumnDef::new(repository::Column::Owner)
.string()
.not_null(),
)
.col(ColumnDef::new(repository::Column::Name).string().not_null())
.col(ColumnDef::new(repository::Column::Description).string())
.to_owned();
create_table(db, &stmt, Repository).await
}
pub async fn create_self_join_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let stmt = sea_query::Table::create()
.table(self_join::Entity)
.col(
ColumnDef::new(self_join::Column::Uuid)
.uuid()
.not_null()
.primary_key(),
)
.col(ColumnDef::new(self_join::Column::UuidRef).uuid())
.col(ColumnDef::new(self_join::Column::Time).time())
.foreign_key(
ForeignKeyCreateStatement::new()
.name("fk-self_join-uuid_ref")
.from_tbl(SelfJoin)
.from_col(self_join::Column::UuidRef)
.to_tbl(SelfJoin)
.to_col(self_join::Column::Uuid),
)
.to_owned();
create_table(db, &stmt, SelfJoin).await
}
pub async fn create_byte_primary_key_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let mut primary_key_col = ColumnDef::new(byte_primary_key::Column::Id);
match db.get_database_backend() {
DbBackend::MySql => primary_key_col.binary_len(3),
DbBackend::Sqlite | DbBackend::Postgres => primary_key_col.binary(),
db => {
return Err(DbErr::BackendNotSupported {
db: db.as_str(),
ctx: "create_byte_primary_key_table",
});
}
};
let stmt = sea_query::Table::create()
.table(byte_primary_key::Entity)
.col(primary_key_col.not_null().primary_key())
.col(
ColumnDef::new(byte_primary_key::Column::Value)
.string()
.not_null(),
)
.to_owned();
create_table_without_asserts(db, &stmt).await
}
pub async fn create_active_enum_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let create_table_stmt = sea_query::Table::create()
.table(active_enum::Entity.table_ref())
.col(
ColumnDef::new(active_enum::Column::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(active_enum::Column::Category).string_len(1))
.col(ColumnDef::new(active_enum::Column::Color).integer())
.col(ColumnDef::new(active_enum::Column::Tea).enumeration(
TeaEnum,
[
TeaVariant::EverydayTea,
TeaVariant::BreakfastTea,
TeaVariant::AfternoonTea,
],
))
.to_owned();
create_table(db, &create_table_stmt, ActiveEnum).await
}
pub async fn create_active_enum_child_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let create_table_stmt = sea_query::Table::create()
.table(active_enum_child::Entity.table_ref())
.col(
ColumnDef::new(active_enum_child::Column::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(
ColumnDef::new(active_enum_child::Column::ParentId)
.integer()
.not_null(),
)
.col(ColumnDef::new(active_enum_child::Column::Category).string_len(1))
.col(ColumnDef::new(active_enum_child::Column::Color).integer())
.col(ColumnDef::new(active_enum_child::Column::Tea).enumeration(
TeaEnum,
[
TeaVariant::EverydayTea,
TeaVariant::BreakfastTea,
TeaVariant::AfternoonTea,
],
))
.foreign_key(
ForeignKeyCreateStatement::new()
.name("fk-active_enum_child-active_enum")
.from_tbl(ActiveEnumChild)
.from_col(active_enum_child::Column::ParentId)
.to_tbl(if cfg!(feature = "sqlx-postgres") {
("public", ActiveEnum).into_table_ref()
} else {
ActiveEnum.into_table_ref()
})
.to_col(active_enum::Column::Id),
)
.to_owned();
create_table(db, &create_table_stmt, ActiveEnumChild).await
}
pub async fn create_satellites_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let stmt = sea_query::Table::create()
.table(satellite::Entity)
.col(
ColumnDef::new(satellite::Column::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(
ColumnDef::new(satellite::Column::SatelliteName)
.string()
.not_null(),
)
.col(
ColumnDef::new(satellite::Column::LaunchDate)
.timestamp_with_time_zone()
.not_null()
.default("2022-01-26 16:24:00"),
)
.col(
ColumnDef::new(satellite::Column::DeploymentDate)
.timestamp_with_time_zone()
.not_null()
.default("2022-01-26 16:24:00"),
)
.to_owned();
create_table(db, &stmt, Satellite).await
}
pub async fn create_transaction_log_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let stmt = sea_query::Table::create()
.table(transaction_log::Entity)
.col(
ColumnDef::new(transaction_log::Column::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(
ColumnDef::new(transaction_log::Column::Date)
.date()
.not_null(),
)
.col(
ColumnDef::new(transaction_log::Column::Time)
.time()
.not_null(),
)
.col(
ColumnDef::new(transaction_log::Column::DateTime)
.date_time()
.not_null(),
)
.col(
ColumnDef::new(transaction_log::Column::DateTimeTz)
.timestamp_with_time_zone()
.not_null(),
)
.to_owned();
create_table(db, &stmt, TransactionLog).await
}
pub async fn create_insert_default_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let create_table_stmt = sea_query::Table::create()
.table(insert_default::Entity.table_ref())
.col(
ColumnDef::new(insert_default::Column::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.to_owned();
create_table(db, &create_table_stmt, InsertDefault).await
}
pub async fn create_json_vec_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let create_table_stmt = sea_query::Table::create()
.table(json_vec::Entity.table_ref())
.col(
ColumnDef::new(json_vec::Column::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(json_vec::Column::StrVec).json())
.to_owned();
create_table(db, &create_table_stmt, JsonVec).await
}
pub async fn create_json_struct_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let stmt = sea_query::Table::create()
.table(json_struct::Entity)
.col(
ColumnDef::new(json_struct::Column::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(json_struct::Column::Json).json().not_null())
.col(
ColumnDef::new(json_struct::Column::JsonValue)
.json()
.not_null(),
)
.col(ColumnDef::new(json_struct::Column::JsonValueOpt).json())
.col(ColumnDef::new(json_struct::Column::JsonNonSerializable).json())
.to_owned();
create_table(db, &stmt, JsonStruct).await
}
pub async fn create_json_string_vec_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let create_table_stmt = sea_query::Table::create()
.table(JsonStringVec.table_ref())
.col(
ColumnDef::new(json_vec_derive::json_string_vec::Column::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(json_vec_derive::json_string_vec::Column::StrVec).json())
.to_owned();
create_table(db, &create_table_stmt, JsonStringVec).await
}
pub async fn create_json_struct_vec_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let create_table_stmt = sea_query::Table::create()
.table(JsonStructVec.table_ref())
.col(
ColumnDef::new(json_vec_derive::json_struct_vec::Column::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(
ColumnDef::new(json_vec_derive::json_struct_vec::Column::StructVec)
.json_binary()
.not_null(),
)
.to_owned();
create_table(db, &create_table_stmt, JsonStructVec).await
}
pub async fn create_collection_table(db: &DbConn) -> Result<ExecResult, DbErr> {
db.execute_raw(sea_orm::Statement::from_string(
db.get_database_backend(),
"CREATE EXTENSION IF NOT EXISTS citext",
))
.await?;
let stmt = sea_query::Table::create()
.table(collection::Entity)
.col(
ColumnDef::new(collection::Column::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(
ColumnDef::new(collection::Column::Name)
.custom("citext")
.not_null(),
)
.col(
ColumnDef::new(collection::Column::Integers)
.array(sea_query::ColumnType::Integer)
.not_null(),
)
.col(ColumnDef::new(collection::Column::IntegersOpt).array(sea_query::ColumnType::Integer))
.col(
ColumnDef::new(collection::Column::Teas)
.array(sea_query::ColumnType::Enum {
name: TeaEnum.into_iden(),
variants: vec![
TeaVariant::EverydayTea.into_iden(),
TeaVariant::BreakfastTea.into_iden(),
TeaVariant::AfternoonTea.into_iden(),
],
})
.not_null(),
)
.col(
ColumnDef::new(collection::Column::TeasOpt).array(sea_query::ColumnType::Enum {
name: TeaEnum.into_iden(),
variants: vec![
TeaVariant::EverydayTea.into_iden(),
TeaVariant::BreakfastTea.into_iden(),
TeaVariant::AfternoonTea.into_iden(),
],
}),
)
.col(
ColumnDef::new(collection::Column::Colors)
.array(sea_query::ColumnType::Integer)
.not_null(),
)
.col(ColumnDef::new(collection::Column::ColorsOpt).array(sea_query::ColumnType::Integer))
.col(
ColumnDef::new(collection::Column::Uuid)
.array(sea_query::ColumnType::Uuid)
.not_null(),
)
.col(
ColumnDef::new(collection::Column::UuidHyphenated)
.array(sea_query::ColumnType::Uuid)
.not_null(),
)
.to_owned();
create_table(db, &stmt, Collection).await
}
#[cfg(feature = "with-ipnetwork")]
pub async fn create_host_network_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let stmt = sea_query::Table::create()
.table(host_network::Entity)
.col(
ColumnDef::new(host_network::Column::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(
ColumnDef::new(host_network::Column::Hostname)
.string()
.not_null(),
)
.col(
ColumnDef::new(host_network::Column::Ipaddress)
.inet()
.not_null(),
)
.col(
ColumnDef::new(host_network::Column::Network)
.cidr()
.not_null(),
)
.to_owned();
create_table(db, &stmt, host_network::Entity).await
}
#[cfg(feature = "with-bigdecimal")]
pub async fn create_pi_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let stmt = sea_query::Table::create()
.table(pi::Entity)
.col(
ColumnDef::new(pi::Column::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(
ColumnDef::new(pi::Column::Decimal)
.decimal_len(11, 10)
.not_null(),
)
.col(
ColumnDef::new(pi::Column::BigDecimal)
.decimal_len(11, 10)
.not_null(),
)
.col(ColumnDef::new(pi::Column::DecimalOpt).decimal_len(11, 10))
.col(ColumnDef::new(pi::Column::BigDecimalOpt).decimal_len(11, 10))
.to_owned();
create_table(db, &stmt, pi::Entity).await
}
pub async fn create_event_trigger_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let stmt = sea_query::Table::create()
.table(event_trigger::Entity)
.col(
ColumnDef::new(event_trigger::Column::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(
ColumnDef::new(event_trigger::Column::Events)
.array(sea_query::ColumnType::String(StringLen::None))
.not_null(),
)
.to_owned();
create_table(db, &stmt, EventTrigger).await
}
pub async fn create_uuid_fmt_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let stmt = sea_query::Table::create()
.table(uuid_fmt::Entity)
.col(
ColumnDef::new(uuid_fmt::Column::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(uuid_fmt::Column::Uuid).uuid().not_null())
.col(
ColumnDef::new(uuid_fmt::Column::UuidBraced)
.uuid()
.not_null(),
)
.col(
ColumnDef::new(uuid_fmt::Column::UuidHyphenated)
.uuid()
.not_null(),
)
.col(
ColumnDef::new(uuid_fmt::Column::UuidSimple)
.uuid()
.not_null(),
)
.col(ColumnDef::new(uuid_fmt::Column::UuidUrn).uuid().not_null())
.to_owned();
create_table(db, &stmt, UuidFmt).await
}
pub async fn create_edit_log_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let stmt = sea_query::Table::create()
.table(edit_log::Entity)
.col(
ColumnDef::new(edit_log::Column::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(edit_log::Column::Action).string().not_null())
.col(ColumnDef::new(edit_log::Column::Values).json().not_null())
.to_owned();
create_table(db, &stmt, EditLog).await
}
pub async fn create_teas_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let create_table_stmt = sea_query::Table::create()
.table(teas::Entity.table_ref())
.col(
ColumnDef::new(teas::Column::Id)
.enumeration(
TeaEnum,
[
TeaVariant::EverydayTea,
TeaVariant::BreakfastTea,
TeaVariant::AfternoonTea,
],
)
.not_null()
.primary_key(),
)
.col(ColumnDef::new(teas::Column::Category).string_len(1))
.col(ColumnDef::new(teas::Column::Color).integer())
.to_owned();
create_table(db, &create_table_stmt, Teas).await
}
pub async fn create_categories_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let create_table_stmt = sea_query::Table::create()
.table(categories::Entity.table_ref())
.col(
ColumnDef::new(categories::Column::Id)
.integer()
.not_null()
.primary_key(),
)
.col(
ColumnDef::new(categories::Column::Categories)
.array(ColumnType::String(StringLen::N(1))),
)
.to_owned();
create_table(db, &create_table_stmt, Categories).await
}
#[cfg(feature = "postgres-vector")]
pub async fn create_embedding_table(db: &DbConn) -> Result<ExecResult, DbErr> {
db.execute_raw(sea_orm::Statement::from_string(
db.get_database_backend(),
"CREATE EXTENSION IF NOT EXISTS vector",
))
.await?;
let create_table_stmt = sea_query::Table::create()
.table(embedding::Entity.table_ref())
.col(
ColumnDef::new(embedding::Column::Id)
.integer()
.not_null()
.primary_key(),
)
.col(
ColumnDef::new(embedding::Column::Embedding)
.vector(None)
.not_null(),
)
.to_owned();
create_table(db, &create_table_stmt, Embedding).await
}
pub async fn create_binary_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let create_table_stmt = sea_query::Table::create()
.table(binary::Entity.table_ref())
.col(
ColumnDef::new(binary::Column::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(binary::Column::Binary).binary().not_null())
.col(
ColumnDef::new(binary::Column::Binary10)
.binary_len(10)
.not_null(),
)
.col(
ColumnDef::new(binary::Column::VarBinary16)
.var_binary(16)
.not_null(),
)
.to_owned();
create_table(db, &create_table_stmt, Binary).await
}
pub async fn create_bits_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let create_table_stmt = sea_query::Table::create()
.table(bits::Entity.table_ref())
.col(
ColumnDef::new(bits::Column::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(bits::Column::Bit0).custom("BIT").not_null())
.col(
ColumnDef::new(bits::Column::Bit1)
.custom("BIT(1)")
.not_null(),
)
.col(
ColumnDef::new(bits::Column::Bit8)
.custom("BIT(8)")
.not_null(),
)
.col(
ColumnDef::new(bits::Column::Bit16)
.custom("BIT(16)")
.not_null(),
)
.col(
ColumnDef::new(bits::Column::Bit32)
.custom("BIT(32)")
.not_null(),
)
.col(
ColumnDef::new(bits::Column::Bit64)
.custom("BIT(64)")
.not_null(),
)
.to_owned();
create_table(db, &create_table_stmt, Bits).await
}
pub async fn create_dyn_table_name_lazy_static_table(db: &DbConn) -> Result<(), DbErr> {
use dyn_table_name::*;
let entities = [Entity { table_name: 1 }, Entity { table_name: 2 }];
for entity in entities {
let create_table_stmt = sea_query::Table::create()
.table(entity.table_ref())
.col(
ColumnDef::new(Column::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(Column::Name).string().not_null())
.to_owned();
create_table(db, &create_table_stmt, entity).await?;
}
Ok(())
}
pub async fn create_value_type_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let general_stmt = sea_query::Table::create()
.table(value_type::value_type_general::Entity)
.col(
ColumnDef::new(value_type::value_type_general::Column::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(
ColumnDef::new(value_type::value_type_general::Column::Number)
.integer()
.not_null(),
)
.col(
ColumnDef::new(value_type::value_type_general::Column::Tag1)
.string()
.not_null(),
)
.col(
ColumnDef::new(value_type::value_type_general::Column::Tag2)
.text()
.not_null(),
)
.to_owned();
create_table(db, &general_stmt, value_type::value_type_general::Entity).await?;
create_table_from_entity(db, value_type::value_type_pk::Entity).await
}
pub async fn create_value_type_postgres_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let postgres_stmt = sea_query::Table::create()
.table(value_type::value_type_pg::Entity)
.col(
ColumnDef::new(value_type::value_type_pg::Column::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(
ColumnDef::new(value_type::value_type_pg::Column::Number)
.integer()
.not_null(),
)
.col(
ColumnDef::new(value_type::value_type_pg::Column::StrVec)
.array(sea_query::ColumnType::String(StringLen::None))
.not_null(),
)
.to_owned();
create_table(db, &postgres_stmt, value_type::value_type_pg::Entity).await
}
@@ -0,0 +1,68 @@
use sea_orm::entity::prelude::*;
#[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum)]
#[sea_orm(rs_type = "String", db_type = "String(StringLen::N(1))")]
pub enum Category {
#[sea_orm(string_value = "B")]
Big,
#[sea_orm(string_value = "S")]
Small,
}
#[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum)]
#[sea_orm(rs_type = "i32", db_type = "Integer")]
pub enum Color {
#[sea_orm(num_value = 0)]
Black,
#[sea_orm(num_value = 1)]
White,
}
// Changed to rs_type to "Enum" for test showcase
// Works the same with rs_type "String"
#[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum, DeriveDisplay)]
#[sea_orm(rs_type = "Enum", db_type = "Enum", enum_name = "tea")]
pub enum Tea {
#[sea_orm(string_value = "EverydayTea")]
EverydayTea,
#[sea_orm(string_value = "BreakfastTea")]
BreakfastTea,
#[sea_orm(string_value = "AfternoonTea")]
AfternoonTea,
}
#[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum, Copy)]
#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "media_type")]
pub enum MediaType {
#[sea_orm(string_value = "UNKNOWN")]
Unknown,
#[sea_orm(string_value = "BITMAP")]
Bitmap,
#[sea_orm(string_value = "DRAWING")]
Drawing,
#[sea_orm(string_value = "AUDIO")]
Audio,
#[sea_orm(string_value = "VIDEO")]
Video,
#[sea_orm(string_value = "MULTIMEDIA")]
Multimedia,
#[sea_orm(string_value = "OFFICE")]
Office,
#[sea_orm(string_value = "TEXT")]
Text,
#[sea_orm(string_value = "EXECUTABLE")]
Executable,
#[sea_orm(string_value = "ARCHIVE")]
Archive,
#[sea_orm(string_value = "3D")]
_3D,
}
#[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum, DeriveDisplay)]
#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "tea")]
pub enum DisplayTea {
#[sea_orm(string_value = "EverydayTea", display_value = "Everyday")]
EverydayTea,
#[sea_orm(string_value = "BreakfastTea", display_value = "Breakfast")]
BreakfastTea,
}
@@ -0,0 +1,27 @@
use sea_orm::entity::prelude::*;
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "self_join")]
pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub uuid: Uuid,
pub uuid_ref: Option<Uuid>,
pub time: Option<Time>,
#[sea_orm(self_ref, relation_enum = "SelfRef", from = "uuid_ref", to = "uuid")]
pub other: BelongsTo<Option<Entity>>,
}
pub struct SelfReferencingLink;
impl Linked for SelfReferencingLink {
type FromEntity = Entity;
type ToEntity = Entity;
fn link(&self) -> Vec<RelationDef> {
vec![Relation::SelfRef.def()]
}
}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,16 @@
use super::sea_orm_active_enums::*;
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "teas")]
pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub id: Tea,
pub category: Option<Category>,
pub color: Option<Color>,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,17 @@
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "transaction_log")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub date: TimeDate,
pub time: TimeTime,
pub date_time: TimeDateTime,
pub date_time_tz: TimeDateTimeWithTimeZone,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,18 @@
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "uuid_fmt")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub uuid: Uuid,
pub uuid_braced: uuid::fmt::Braced,
pub uuid_hyphenated: uuid::fmt::Hyphenated,
pub uuid_simple: uuid::fmt::Simple,
pub uuid_urn: uuid::fmt::Urn,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
@@ -0,0 +1,213 @@
pub mod value_type_general {
use super::*;
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "value_type")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub number: MyInteger,
pub tag_1: Tag1,
pub tag_2: Tag2,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
}
pub mod value_type_pg {
use super::*;
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "value_type_postgres")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub number: MyInteger,
pub str_vec: StringVec,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
}
pub mod value_type_pk {
use super::*;
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "value_type_pk")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: MyInteger,
pub val: MyInteger,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
}
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, DeriveValueType)]
pub struct MyInteger(pub i32);
impl<T> From<T> for MyInteger
where
T: Into<i32>,
{
fn from(v: T) -> MyInteger {
MyInteger(v.into())
}
}
#[derive(Clone, Debug, PartialEq, Eq, DeriveValueType)]
pub struct StringVec(pub Vec<String>);
#[derive(Clone, Debug, PartialEq, Eq, DeriveValueType)]
#[sea_orm(try_getable_array)]
pub struct GoodId(pub i32);
#[cfg(feature = "postgres-array")]
use sea_orm::FromQueryResult;
#[cfg(feature = "postgres-array")]
#[derive(Debug, FromQueryResult)]
pub struct GoodIdArray {
pub ids: Vec<GoodId>,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, DeriveValueType)]
#[sea_orm(value_type = "String")]
pub enum Tag1 {
Hard,
Soft,
}
impl std::fmt::Display for Tag1 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match self {
Self::Hard => "hard",
Self::Soft => "soft",
}
)
}
}
impl std::str::FromStr for Tag1 {
type Err = sea_query::ValueTypeErr;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
"hard" => Self::Hard,
"soft" => Self::Soft,
_ => return Err(sea_query::ValueTypeErr),
})
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, DeriveValueType)]
#[sea_orm(
value_type = "String",
from_str = "Tag2::from_str",
to_str = "Tag2::to_str",
column_type = "Text"
)]
pub enum Tag2 {
Color,
Grey,
}
impl Tag2 {
fn to_str(&self) -> &'static str {
match self {
Self::Color => "color",
Self::Grey => "grey",
}
}
fn from_str(s: &str) -> Result<Self, sea_query::ValueTypeErr> {
Ok(match s {
"color" => Self::Color,
"grey" => Self::Grey,
_ => return Err(sea_query::ValueTypeErr),
})
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, DeriveValueType)]
#[sea_orm(value_type = "String")]
pub struct Tag3 {
pub i: i64,
}
impl std::fmt::Display for Tag3 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.i)
}
}
impl std::str::FromStr for Tag3 {
type Err = std::num::ParseIntError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let i: i64 = s.parse()?;
Ok(Self { i })
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, DeriveValueType)]
#[sea_orm(value_type = "String")]
pub struct Tag4(pub i64);
impl std::fmt::Display for Tag4 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl std::str::FromStr for Tag4 {
type Err = std::num::ParseIntError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let i: i64 = s.parse()?;
Ok(Self(i))
}
}
#[derive(Clone, Debug, PartialEq, Eq, DeriveValueType)]
#[sea_orm(value_type = "String")]
// Test with inner type that doesn't implement ToString/FromStr
pub struct Tag5(pub std::path::PathBuf);
impl std::fmt::Display for Tag5 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0.display())
}
}
impl std::str::FromStr for Tag5 {
type Err = std::num::ParseIntError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self(std::path::PathBuf::from(s)))
}
}
// Test for try_from_u64 attribute with type alias
type UserId = i32;
#[derive(Clone, Debug, PartialEq, Eq, DeriveValueType)]
#[sea_orm(try_from_u64)]
pub struct MyUserId(pub UserId);
+134
View File
@@ -0,0 +1,134 @@
pub mod film {
use sea_orm::entity::prelude::*;
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "film")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
#[sea_orm(unique)]
pub title: String,
#[sea_orm(has_many, via = "film_actor")]
pub actors: HasMany<super::actor::Entity>,
}
impl ActiveModelBehavior for ActiveModel {}
}
pub mod actor {
use sea_orm::entity::prelude::*;
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "actor")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
#[sea_orm(unique)]
pub name: String,
#[sea_orm(has_many, via = "film_actor")]
pub films: HasMany<super::film::Entity>,
}
impl ActiveModelBehavior for ActiveModel {}
}
pub mod film_actor {
use sea_orm::entity::prelude::*;
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "film_actor")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
#[sea_orm(unique_key = "film_actor")]
pub film_id: i32,
#[sea_orm(unique_key = "film_actor")]
pub actor_id: i32,
#[sea_orm(belongs_to, from = "film_id", to = "id")]
pub film: BelongsTo<super::film::Entity>,
#[sea_orm(belongs_to, from = "actor_id", to = "id")]
pub actor: BelongsTo<super::actor::Entity>,
}
impl ActiveModelBehavior for ActiveModel {}
}
pub mod staff {
use sea_orm::entity::prelude::*;
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "staff")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub name: String,
pub reports_to_id: Option<i32>,
#[sea_orm(
self_ref,
relation_enum = "ReportsTo",
relation_reverse = "Manages",
from = "reports_to_id",
to = "id"
)]
pub reports_to: BelongsTo<Option<Entity>>,
#[sea_orm(self_ref, relation_enum = "Manages", relation_reverse = "ReportsTo")]
pub manages: HasMany<Entity>,
}
impl ActiveModelBehavior for ActiveModel {}
}
pub mod staff_mono {
use sea_orm::entity::prelude::*;
#[sea_orm::model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "staff")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub name: String,
pub reports_to_id: Option<i32>,
#[sea_orm(
self_ref,
relation_enum = "ReportsTo",
from = "reports_to_id",
to = "id"
)]
pub reports_to: BelongsTo<Option<Entity>>,
}
impl ActiveModelBehavior for ActiveModel {}
}
pub mod staff_compact {
use sea_orm::entity::prelude::*;
#[sea_orm::compact_model]
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "staff")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub name: String,
pub reports_to_id: Option<i32>,
#[sea_orm(self_ref, relation_enum = "ReportsTo")]
pub reports_to: BelongsTo<Option<Entity>>,
#[sea_orm(self_ref, relation_enum = "Manages")]
pub manages: HasMany<Entity>,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
#[sea_orm(belongs_to = "Entity", from = "Column::ReportsToId", to = "Column::Id")]
ReportsTo,
#[sea_orm(has_many = "Entity", via_rel = "Relation::ReportsTo")]
Manages,
}
impl ActiveModelBehavior for ActiveModel {}
}
+38
View File
@@ -0,0 +1,38 @@
pub mod bakery_chain;
pub mod bakery_dense;
pub mod blogger;
pub mod blogger_legacy;
pub mod features;
pub mod film_store;
#[cfg(not(feature = "sync"))]
pub mod runtime;
pub mod setup;
use sea_orm::DatabaseConnection;
pub struct TestContext {
base_url: String,
db_name: String,
pub db: DatabaseConnection,
}
impl TestContext {
pub async fn new(test_name: &str) -> Self {
dotenv::from_filename(".env.local").ok();
dotenv::from_filename(".env").ok();
let base_url =
std::env::var("DATABASE_URL").expect("Environment variable 'DATABASE_URL' not set");
let db: DatabaseConnection = setup::setup(&base_url, test_name).await;
Self {
base_url,
db_name: test_name.to_string(),
db,
}
}
pub async fn delete(&self) {
setup::tear_down(&self.base_url, &self.db_name).await;
}
}
+17
View File
@@ -0,0 +1,17 @@
#[cfg(feature = "runtime-async-std")]
#[macro_export]
macro_rules! block_on {
($($expr:tt)*) => {
::async_std::task::block_on( $($expr)* )
};
}
#[cfg(feature = "runtime-tokio")]
#[macro_export]
macro_rules! block_on {
($($expr:tt)*) => {
::tokio::runtime::Runtime::new()
.unwrap()
.block_on( $($expr)* )
};
}
@@ -0,0 +1,4 @@
To re-generate diagram, run at project root:
```sh
DATABASE_URL="postgres://sea:sea@localhost/sakila" cargo run --manifest-path sea-orm-cli/Cargo.toml -- generate entity -o tests/common/sakila --entity-format dense --er-diagram
```
@@ -0,0 +1,145 @@
erDiagram
actor {
int actor_id PK
varchar first_name
varchar last_name
datetime last_update
}
address {
int address_id PK
varchar address
varchar address2
varchar district
int city_id FK
varchar postal_code
varchar phone
datetime last_update
}
category {
int category_id PK
varchar name
datetime last_update
}
city {
int city_id PK
varchar city
int country_id FK
datetime last_update
}
country {
int country_id PK
varchar country
datetime last_update
}
customer {
int customer_id PK
int store_id FK
varchar first_name
varchar last_name
varchar email
int address_id FK
bool activebool
date create_date
datetime last_update
int active
}
film {
int film_id PK
varchar title
text description
int release_year
int language_id FK
int original_language_id FK
int rental_duration
decimal rental_rate
int length
decimal replacement_cost
enum rating
datetime last_update
array special_features
custom fulltext
json metadata
}
film_actor {
int actor_id PK,FK
int film_id PK,FK
datetime last_update
}
film_category {
int film_id PK,FK
int category_id PK,FK
datetime last_update
}
inventory {
int inventory_id PK
int film_id FK
int store_id FK
datetime last_update
}
language {
int language_id PK
char name
datetime last_update
}
payment {
int payment_id PK
int customer_id FK
int staff_id FK
int rental_id FK
decimal amount
datetime payment_date
}
rental {
int rental_id PK
datetime rental_date UK
int inventory_id FK,UK
int customer_id FK,UK
datetime return_date
int staff_id FK
datetime last_update
}
staff {
int staff_id PK
varchar first_name
varchar last_name
int address_id FK
int reports_to_id FK
varchar email
int store_id FK
bool active
varchar username
varchar password
datetime last_update
blob picture
}
store {
int store_id PK
int manager_staff_id FK,UK
int address_id FK
datetime last_update
}
actor }o--o{ film : "[film_actor]"
address }o--|| city : "city_id"
category }o--o{ film : "[film_category]"
city }o--|| country : "country_id"
customer }o--|| address : "address_id"
customer }o--|| store : "store_id"
film }o--|| language : "language_id"
film }o--|| language : "original_language_id"
film_actor }o--|| actor : "actor_id"
film_actor }o--|| film : "film_id"
film_category }o--|| category : "category_id"
film_category }o--|| film : "film_id"
inventory }o--|| film : "film_id"
inventory }o--|| store : "store_id"
payment }o--|| customer : "customer_id"
payment }o--|| rental : "rental_id"
payment }o--|| staff : "staff_id"
rental }o--|| customer : "customer_id"
rental }o--|| inventory : "inventory_id"
rental }o--|| staff : "staff_id"
staff }o--|| address : "address_id"
staff }o--|| staff : "reports_to_id"
staff }o--|| store : "store_id"
store }o--|| address : "address_id"
store }o--|| staff : "manager_staff_id"
+190
View File
@@ -0,0 +1,190 @@
use pretty_assertions::assert_eq;
use sea_orm::{
ColumnTrait, ColumnType, ConnectOptions, ConnectionTrait, Database, DatabaseBackend,
DatabaseConnection, DbBackend, DbConn, DbErr, EntityTrait, ExecResult, Iterable, Schema,
Statement,
};
use sea_query::{
SeaRc, Table, TableCreateStatement,
extension::postgres::{Type, TypeCreateStatement},
};
pub async fn setup(base_url: &str, db_name: &str) -> DatabaseConnection {
if cfg!(feature = "sqlx-mysql") {
let url = format!("{base_url}/mysql");
let db = Database::connect(&url).await.unwrap();
let _drop_db_result = db
.execute_raw(Statement::from_string(
DatabaseBackend::MySql,
format!("DROP DATABASE IF EXISTS `{db_name}`;"),
))
.await;
let _create_db_result = db
.execute_raw(Statement::from_string(
DatabaseBackend::MySql,
format!("CREATE DATABASE `{db_name}`;"),
))
.await;
let url = format!("{base_url}/{db_name}");
let mut options: ConnectOptions = url.into();
options.sqlx_logging(false);
Database::connect(options).await.unwrap()
} else if cfg!(feature = "sqlx-postgres") {
let url = format!("{base_url}/postgres");
let db = Database::connect(&url).await.unwrap();
let _drop_db_result = db
.execute_raw(Statement::from_string(
DatabaseBackend::Postgres,
format!("DROP DATABASE IF EXISTS \"{db_name}\";"),
))
.await;
let _create_db_result = db
.execute_raw(Statement::from_string(
DatabaseBackend::Postgres,
format!("CREATE DATABASE \"{db_name}\";"),
))
.await;
let url = format!("{base_url}/{db_name}");
let mut options: ConnectOptions = url.into();
options.sqlx_logging(false);
Database::connect(options).await.unwrap()
} else {
let mut options: ConnectOptions = base_url.into();
options.sqlx_logging(false);
Database::connect(options).await.unwrap()
}
}
pub async fn tear_down(base_url: &str, db_name: &str) {
if cfg!(feature = "sqlx-mysql") {
let url = format!("{base_url}/mysql");
let db = Database::connect(&url).await.unwrap();
let _ = db
.execute_raw(Statement::from_string(
DatabaseBackend::MySql,
format!("DROP DATABASE IF EXISTS \"{db_name}\";"),
))
.await;
} else if cfg!(feature = "sqlx-postgres") {
let url = format!("{base_url}/postgres");
let db = Database::connect(&url).await.unwrap();
let _ = db
.execute_raw(Statement::from_string(
DatabaseBackend::Postgres,
format!("DROP DATABASE IF EXISTS \"{db_name}\";"),
))
.await;
};
}
pub async fn create_enum<E>(
db: &DbConn,
creates: &[TypeCreateStatement],
entity: E,
) -> Result<(), DbErr>
where
E: EntityTrait,
{
let builder = db.get_database_backend();
if builder == DbBackend::Postgres {
for col in E::Column::iter() {
let col_def = col.def();
let col_type = col_def.get_column_type();
if !matches!(col_type, ColumnType::Enum { .. }) {
continue;
}
let name = match col_type {
ColumnType::Enum { name, .. } => name,
_ => unreachable!(),
};
db.execute(Type::drop().name(name.clone()).if_exists().cascade())
.await?;
}
}
let expect_stmts: Vec<Statement> = creates.iter().map(|stmt| builder.build(stmt)).collect();
let schema = Schema::new(builder);
let create_from_entity_stmts: Vec<Statement> = schema
.create_enum_from_entity(entity)
.iter()
.map(|stmt| builder.build(stmt))
.collect();
assert_eq!(expect_stmts, create_from_entity_stmts);
for stmt in creates.iter() {
db.execute(stmt).await?;
}
Ok(())
}
pub async fn create_table<E>(
db: &DbConn,
create: &TableCreateStatement,
entity: E,
) -> Result<ExecResult, DbErr>
where
E: EntityTrait,
{
let builder = db.get_database_backend();
let schema = Schema::new(builder);
assert_eq!(
builder.build(&schema.create_table_from_entity(entity)),
builder.build(create)
);
create_table_without_asserts(db, create).await
}
pub async fn create_table_with_index<E>(
db: &DbConn,
create: &TableCreateStatement,
entity: E,
) -> Result<ExecResult, DbErr>
where
E: EntityTrait,
{
let res = create_table(db, create, entity).await?;
let backend = db.get_database_backend();
for stmt in Schema::new(backend).create_index_from_entity(entity) {
db.execute(&stmt).await?;
}
Ok(res)
}
pub async fn create_table_from_entity<E>(db: &DbConn, entity: E) -> Result<ExecResult, DbErr>
where
E: EntityTrait,
{
let builder = db.get_database_backend();
let schema = Schema::new(builder);
let stmt = schema.create_table_from_entity(entity);
db.execute(&stmt).await
}
pub async fn create_table_without_asserts(
db: &DbConn,
create: &TableCreateStatement,
) -> Result<ExecResult, DbErr> {
let builder = db.get_database_backend();
if builder != DbBackend::Sqlite {
let stmt = Table::drop()
.table(create.get_table_name().unwrap().clone())
.if_exists()
.cascade()
.take();
db.execute(&stmt).await?;
}
db.execute(create).await
}
pub fn rust_dec<T: ToString>(v: T) -> rust_decimal::Decimal {
use std::str::FromStr;
rust_decimal::Decimal::from_str(&v.to_string()).unwrap()
}