Codegen not depends on sea-schema & sqlx
This commit is contained in:
parent
6224bb6d5f
commit
0b10d30c64
@ -5,7 +5,6 @@ members = [
|
|||||||
"sea-orm-codegen",
|
"sea-orm-codegen",
|
||||||
"sea-orm-cli",
|
"sea-orm-cli",
|
||||||
"examples/sqlx-mysql",
|
"examples/sqlx-mysql",
|
||||||
"examples/codegen",
|
|
||||||
"examples/cli",
|
"examples/cli",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
DATABASE_URI=mysql://sea:sea@localhost/bakery
|
DATABASE_URL=mysql://sea:sea@localhost/bakery
|
||||||
DATABASE_SCHEMA=bakery
|
DATABASE_SCHEMA=bakery
|
@ -1,14 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "sea-orm-codegen-example"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2018"
|
|
||||||
publish = false
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
async-std = { version = "^1.9", features = ["attributes"] }
|
|
||||||
sea-orm = { path = "../../" }
|
|
||||||
sea-orm-codegen = { path = "../../sea-orm-codegen" }
|
|
||||||
sea-query = { version = "~0.12.8" }
|
|
||||||
strum = { version = "^0.20", features = ["derive"] }
|
|
||||||
serde_json = { version = "^1" }
|
|
||||||
quote = { version = "^1" }
|
|
@ -1,12 +0,0 @@
|
|||||||
# SeaORM Entity Generator Example
|
|
||||||
|
|
||||||
Prepare:
|
|
||||||
|
|
||||||
Setup a test database and configure the connection string in `main.rs`.
|
|
||||||
Run `bakery.sql` to setup the test table and data.
|
|
||||||
|
|
||||||
Running:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cargo run
|
|
||||||
```
|
|
@ -1,75 +0,0 @@
|
|||||||
//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0
|
|
||||||
|
|
||||||
use sea_orm::entity::prelude::*;
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Default, Debug, DeriveEntity)]
|
|
||||||
pub struct Entity;
|
|
||||||
|
|
||||||
impl EntityName for Entity {
|
|
||||||
fn table_name(&self) -> &str {
|
|
||||||
"cake"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)]
|
|
||||||
pub struct Model {
|
|
||||||
pub id: i32,
|
|
||||||
pub name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
|
|
||||||
pub enum Column {
|
|
||||||
Id,
|
|
||||||
Name,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
|
|
||||||
pub enum PrimaryKey {
|
|
||||||
Id,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PrimaryKeyTrait for PrimaryKey {
|
|
||||||
fn auto_increment() -> bool {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, EnumIter)]
|
|
||||||
pub enum Relation {
|
|
||||||
Fruit,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ColumnTrait for Column {
|
|
||||||
type EntityName = Entity;
|
|
||||||
fn def(&self) -> ColumnDef {
|
|
||||||
match self {
|
|
||||||
Self::Id => ColumnType::Integer.def(),
|
|
||||||
Self::Name => ColumnType::String(Some(255u32)).def(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RelationTrait for Relation {
|
|
||||||
fn def(&self) -> RelationDef {
|
|
||||||
match self {
|
|
||||||
Self::Fruit => Entity::has_many(super::fruit::Entity).into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Related<super::fruit::Entity> for Entity {
|
|
||||||
fn to() -> RelationDef {
|
|
||||||
Relation::Fruit.def()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Related<super::filling::Entity> for Entity {
|
|
||||||
fn to() -> RelationDef {
|
|
||||||
super::cake_filling::Relation::Filling.def()
|
|
||||||
}
|
|
||||||
fn via() -> Option<RelationDef> {
|
|
||||||
Some(super::cake_filling::Relation::Cake.def().rev())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ActiveModelBehavior for ActiveModel {}
|
|
@ -1,81 +0,0 @@
|
|||||||
//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0
|
|
||||||
|
|
||||||
use sea_orm::entity::prelude::*;
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Default, Debug, DeriveEntity)]
|
|
||||||
pub struct Entity;
|
|
||||||
|
|
||||||
impl EntityName for Entity {
|
|
||||||
fn table_name(&self) -> &str {
|
|
||||||
"cake_filling"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)]
|
|
||||||
pub struct Model {
|
|
||||||
pub cake_id: i32,
|
|
||||||
pub filling_id: i32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
|
|
||||||
pub enum Column {
|
|
||||||
CakeId,
|
|
||||||
FillingId,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
|
|
||||||
pub enum PrimaryKey {
|
|
||||||
CakeId,
|
|
||||||
FillingId,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PrimaryKeyTrait for PrimaryKey {
|
|
||||||
fn auto_increment() -> bool {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, EnumIter)]
|
|
||||||
pub enum Relation {
|
|
||||||
Cake,
|
|
||||||
Filling,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ColumnTrait for Column {
|
|
||||||
type EntityName = Entity;
|
|
||||||
fn def(&self) -> ColumnDef {
|
|
||||||
match self {
|
|
||||||
Self::CakeId => ColumnType::Integer.def(),
|
|
||||||
Self::FillingId => ColumnType::Integer.def(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RelationTrait for Relation {
|
|
||||||
fn def(&self) -> RelationDef {
|
|
||||||
match self {
|
|
||||||
Self::Cake => Entity::belongs_to(super::cake::Entity)
|
|
||||||
.from(Column::CakeId)
|
|
||||||
.to(super::cake::Column::Id)
|
|
||||||
.into(),
|
|
||||||
Self::Filling => Entity::belongs_to(super::filling::Entity)
|
|
||||||
.from(Column::FillingId)
|
|
||||||
.to(super::filling::Column::Id)
|
|
||||||
.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Related<super::cake::Entity> for Entity {
|
|
||||||
fn to() -> RelationDef {
|
|
||||||
Relation::Cake.def()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Related<super::filling::Entity> for Entity {
|
|
||||||
fn to() -> RelationDef {
|
|
||||||
Relation::Filling.def()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ActiveModelBehavior for ActiveModel {}
|
|
@ -1,67 +0,0 @@
|
|||||||
//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0
|
|
||||||
|
|
||||||
use sea_orm::entity::prelude::*;
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Default, Debug, DeriveEntity)]
|
|
||||||
pub struct Entity;
|
|
||||||
|
|
||||||
impl EntityName for Entity {
|
|
||||||
fn table_name(&self) -> &str {
|
|
||||||
"filling"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)]
|
|
||||||
pub struct Model {
|
|
||||||
pub id: i32,
|
|
||||||
pub name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
|
|
||||||
pub enum Column {
|
|
||||||
Id,
|
|
||||||
Name,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
|
|
||||||
pub enum PrimaryKey {
|
|
||||||
Id,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PrimaryKeyTrait for PrimaryKey {
|
|
||||||
fn auto_increment() -> bool {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, EnumIter)]
|
|
||||||
pub enum Relation {}
|
|
||||||
|
|
||||||
impl ColumnTrait for Column {
|
|
||||||
type EntityName = Entity;
|
|
||||||
fn def(&self) -> ColumnDef {
|
|
||||||
match self {
|
|
||||||
Self::Id => ColumnType::Integer.def(),
|
|
||||||
Self::Name => ColumnType::String(Some(255u32)).def(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RelationTrait for Relation {
|
|
||||||
fn def(&self) -> RelationDef {
|
|
||||||
match self {
|
|
||||||
_ => panic!("No RelationDef"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Related<super::cake::Entity> for Entity {
|
|
||||||
fn to() -> RelationDef {
|
|
||||||
super::cake_filling::Relation::Cake.def()
|
|
||||||
}
|
|
||||||
fn via() -> Option<RelationDef> {
|
|
||||||
Some(super::cake_filling::Relation::Filling.def().rev())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ActiveModelBehavior for ActiveModel {}
|
|
@ -1,80 +0,0 @@
|
|||||||
//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0
|
|
||||||
|
|
||||||
use sea_orm::entity::prelude::*;
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Default, Debug, DeriveEntity)]
|
|
||||||
pub struct Entity;
|
|
||||||
|
|
||||||
impl EntityName for Entity {
|
|
||||||
fn table_name(&self) -> &str {
|
|
||||||
"fruit"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)]
|
|
||||||
pub struct Model {
|
|
||||||
pub id: i32,
|
|
||||||
pub name: String,
|
|
||||||
pub cake_id: Option<i32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
|
|
||||||
pub enum Column {
|
|
||||||
Id,
|
|
||||||
Name,
|
|
||||||
CakeId,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
|
|
||||||
pub enum PrimaryKey {
|
|
||||||
Id,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PrimaryKeyTrait for PrimaryKey {
|
|
||||||
fn auto_increment() -> bool {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, EnumIter)]
|
|
||||||
pub enum Relation {
|
|
||||||
Cake,
|
|
||||||
Vendor,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ColumnTrait for Column {
|
|
||||||
type EntityName = Entity;
|
|
||||||
fn def(&self) -> ColumnDef {
|
|
||||||
match self {
|
|
||||||
Self::Id => ColumnType::Integer.def(),
|
|
||||||
Self::Name => ColumnType::String(Some(255u32)).def(),
|
|
||||||
Self::CakeId => ColumnType::Integer.def().null(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RelationTrait for Relation {
|
|
||||||
fn def(&self) -> RelationDef {
|
|
||||||
match self {
|
|
||||||
Self::Cake => Entity::belongs_to(super::cake::Entity)
|
|
||||||
.from(Column::CakeId)
|
|
||||||
.to(super::cake::Column::Id)
|
|
||||||
.into(),
|
|
||||||
Self::Vendor => Entity::has_many(super::vendor::Entity).into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Related<super::cake::Entity> for Entity {
|
|
||||||
fn to() -> RelationDef {
|
|
||||||
Relation::Cake.def()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Related<super::vendor::Entity> for Entity {
|
|
||||||
fn to() -> RelationDef {
|
|
||||||
Relation::Vendor.def()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ActiveModelBehavior for ActiveModel {}
|
|
@ -1,7 +0,0 @@
|
|||||||
//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0
|
|
||||||
|
|
||||||
pub mod cake;
|
|
||||||
pub mod cake_filling;
|
|
||||||
pub mod filling;
|
|
||||||
pub mod fruit;
|
|
||||||
pub mod vendor;
|
|
@ -1,7 +0,0 @@
|
|||||||
//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0
|
|
||||||
|
|
||||||
pub use super::cake::Entity as Cake;
|
|
||||||
pub use super::cake_filling::Entity as CakeFilling;
|
|
||||||
pub use super::filling::Entity as Filling;
|
|
||||||
pub use super::fruit::Entity as Fruit;
|
|
||||||
pub use super::vendor::Entity as Vendor;
|
|
@ -1,72 +0,0 @@
|
|||||||
//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0
|
|
||||||
|
|
||||||
use sea_orm::entity::prelude::*;
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Default, Debug, DeriveEntity)]
|
|
||||||
pub struct Entity;
|
|
||||||
|
|
||||||
impl EntityName for Entity {
|
|
||||||
fn table_name(&self) -> &str {
|
|
||||||
"vendor"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)]
|
|
||||||
pub struct Model {
|
|
||||||
pub id: i32,
|
|
||||||
pub name: String,
|
|
||||||
pub fruit_id: Option<i32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
|
|
||||||
pub enum Column {
|
|
||||||
Id,
|
|
||||||
Name,
|
|
||||||
FruitId,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
|
|
||||||
pub enum PrimaryKey {
|
|
||||||
Id,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PrimaryKeyTrait for PrimaryKey {
|
|
||||||
fn auto_increment() -> bool {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, EnumIter)]
|
|
||||||
pub enum Relation {
|
|
||||||
Fruit,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ColumnTrait for Column {
|
|
||||||
type EntityName = Entity;
|
|
||||||
fn def(&self) -> ColumnDef {
|
|
||||||
match self {
|
|
||||||
Self::Id => ColumnType::Integer.def(),
|
|
||||||
Self::Name => ColumnType::String(Some(255u32)).def(),
|
|
||||||
Self::FruitId => ColumnType::Integer.def().null(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RelationTrait for Relation {
|
|
||||||
fn def(&self) -> RelationDef {
|
|
||||||
match self {
|
|
||||||
Self::Fruit => Entity::belongs_to(super::fruit::Entity)
|
|
||||||
.from(Column::FruitId)
|
|
||||||
.to(super::fruit::Column::Id)
|
|
||||||
.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Related<super::fruit::Entity> for Entity {
|
|
||||||
fn to() -> RelationDef {
|
|
||||||
Relation::Fruit.def()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ActiveModelBehavior for ActiveModel {}
|
|
@ -1,16 +0,0 @@
|
|||||||
mod entity;
|
|
||||||
|
|
||||||
use sea_orm_codegen::{EntityGenerator, Error};
|
|
||||||
|
|
||||||
#[async_std::main]
|
|
||||||
async fn main() -> Result<(), Error> {
|
|
||||||
let uri = "mysql://sea:sea@localhost/bakery";
|
|
||||||
let schema = "bakery";
|
|
||||||
|
|
||||||
let _generator = EntityGenerator::discover(uri, schema)
|
|
||||||
.await?
|
|
||||||
.transform()?
|
|
||||||
.generate("src/entity")?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
@ -20,3 +20,36 @@ clap = { version = "^2.33.3" }
|
|||||||
dotenv = { version = "^0.15" }
|
dotenv = { version = "^0.15" }
|
||||||
async-std = { version = "^1.9", features = [ "attributes" ] }
|
async-std = { version = "^1.9", features = [ "attributes" ] }
|
||||||
sea-orm-codegen = { path = "../sea-orm-codegen" }
|
sea-orm-codegen = { path = "../sea-orm-codegen" }
|
||||||
|
sea-schema = { version = "^0.2", default-features = false, features = [
|
||||||
|
"sqlx-mysql",
|
||||||
|
"discovery",
|
||||||
|
"writer",
|
||||||
|
] }
|
||||||
|
sqlx = { version = "^0.5", default-features = false, features = [ "mysql" ] }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = [ "runtime-async-std-native-tls" ]
|
||||||
|
runtime-actix-native-tls = [
|
||||||
|
"sqlx/runtime-actix-native-tls",
|
||||||
|
"sea-schema/runtime-actix-native-tls",
|
||||||
|
]
|
||||||
|
runtime-async-std-native-tls = [
|
||||||
|
"sqlx/runtime-async-std-native-tls",
|
||||||
|
"sea-schema/runtime-async-std-native-tls",
|
||||||
|
]
|
||||||
|
runtime-tokio-native-tls = [
|
||||||
|
"sqlx/runtime-tokio-native-tls",
|
||||||
|
"sea-schema/runtime-tokio-native-tls",
|
||||||
|
]
|
||||||
|
runtime-actix-rustls = [
|
||||||
|
"sqlx/runtime-actix-rustls",
|
||||||
|
"sea-schema/runtime-actix-rustls",
|
||||||
|
]
|
||||||
|
runtime-async-std-rustls = [
|
||||||
|
"sqlx/runtime-async-std-rustls",
|
||||||
|
"sea-schema/runtime-async-std-rustls",
|
||||||
|
]
|
||||||
|
runtime-tokio-rustls = [
|
||||||
|
"sqlx/runtime-tokio-rustls",
|
||||||
|
"sea-schema/runtime-tokio-rustls",
|
||||||
|
]
|
||||||
|
@ -9,5 +9,5 @@ cargo run -- -h
|
|||||||
Running Entity Generator:
|
Running Entity Generator:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cargo run -- entity generate -u mysql://sea:sea@localhost/bakery -s bakery -o out
|
cargo run -- entity generate -url mysql://sea:sea@localhost/bakery -schema bakery -o out
|
||||||
```
|
```
|
||||||
|
@ -8,18 +8,18 @@ pub fn build_cli() -> App<'static, 'static> {
|
|||||||
SubCommand::with_name("entity")
|
SubCommand::with_name("entity")
|
||||||
.about("Generate entity")
|
.about("Generate entity")
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("DATABASE_URI")
|
Arg::with_name("DATABASE_URL")
|
||||||
.long("uri")
|
.long("database-url")
|
||||||
.short("u")
|
.short("url")
|
||||||
.help("Database URI")
|
.help("Database URL")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.required(true)
|
.required(true)
|
||||||
.env("DATABASE_URI"),
|
.env("DATABASE_URL"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("DATABASE_SCHEMA")
|
Arg::with_name("DATABASE_SCHEMA")
|
||||||
.long("schema")
|
.long("database-schema")
|
||||||
.short("s")
|
.short("schema")
|
||||||
.help("Database schema")
|
.help("Database schema")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.required(true)
|
.required(true)
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
use clap::ArgMatches;
|
use clap::ArgMatches;
|
||||||
use dotenv::dotenv;
|
use dotenv::dotenv;
|
||||||
use sea_orm_codegen::EntityGenerator;
|
use sea_orm_codegen::{EntityTransformer, OutputFile};
|
||||||
use std::{error::Error, fmt::Display};
|
use sea_schema::mysql::discovery::SchemaDiscovery;
|
||||||
|
use sqlx::MySqlPool;
|
||||||
|
use std::{error::Error, fmt::Display, fs, io::Write, path::Path, process::Command};
|
||||||
|
|
||||||
mod cli;
|
mod cli;
|
||||||
|
|
||||||
@ -22,13 +24,35 @@ async fn main() {
|
|||||||
async fn run_generate_command(matches: &ArgMatches<'_>) -> Result<(), Box<dyn Error>> {
|
async fn run_generate_command(matches: &ArgMatches<'_>) -> Result<(), Box<dyn Error>> {
|
||||||
match matches.subcommand() {
|
match matches.subcommand() {
|
||||||
("entity", Some(args)) => {
|
("entity", Some(args)) => {
|
||||||
let uri = args.value_of("DATABASE_URI").unwrap();
|
let url = args.value_of("DATABASE_URL").unwrap();
|
||||||
let schema = args.value_of("DATABASE_SCHEMA").unwrap();
|
let schema = args.value_of("DATABASE_SCHEMA").unwrap();
|
||||||
let output_dir = args.value_of("OUTPUT_DIR").unwrap();
|
let output_dir = args.value_of("OUTPUT_DIR").unwrap();
|
||||||
EntityGenerator::discover(uri, schema)
|
|
||||||
.await?
|
let connection = MySqlPool::connect(url).await?;
|
||||||
.transform()?
|
let schema_discovery = SchemaDiscovery::new(connection, schema);
|
||||||
.generate(output_dir)?;
|
let schema = schema_discovery.discover().await;
|
||||||
|
let table_stmts = schema
|
||||||
|
.tables
|
||||||
|
.into_iter()
|
||||||
|
.map(|schema| schema.write())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let output = EntityTransformer::transform(table_stmts)?.generate();
|
||||||
|
|
||||||
|
let dir = Path::new(output_dir);
|
||||||
|
fs::create_dir_all(dir)?;
|
||||||
|
|
||||||
|
for OutputFile { name, content } in output.files.iter() {
|
||||||
|
let file_path = dir.join(name);
|
||||||
|
let mut file = fs::File::create(file_path)?;
|
||||||
|
file.write_all(content.as_bytes())?;
|
||||||
|
}
|
||||||
|
for OutputFile { name, .. } in output.files.iter() {
|
||||||
|
Command::new("rustfmt")
|
||||||
|
.arg(dir.join(name))
|
||||||
|
.spawn()?
|
||||||
|
.wait()?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => unreachable!("You should never see this message"),
|
_ => unreachable!("You should never see this message"),
|
||||||
};
|
};
|
||||||
|
@ -16,13 +16,7 @@ name = "sea_orm_codegen"
|
|||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
sea-schema = { version = "^0.2", default-features = false, features = [
|
|
||||||
"sqlx-mysql",
|
|
||||||
"discovery",
|
|
||||||
"writer",
|
|
||||||
] }
|
|
||||||
sea-query = { version = "~0.12.8" }
|
sea-query = { version = "~0.12.8" }
|
||||||
sqlx = { version = "^0.5", default-features = false, features = ["mysql"] }
|
|
||||||
syn = { version = "^1", default-features = false, features = [
|
syn = { version = "^1", default-features = false, features = [
|
||||||
"derive",
|
"derive",
|
||||||
"parsing",
|
"parsing",
|
||||||
@ -36,29 +30,3 @@ proc-macro2 = "^1"
|
|||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
async-std = { version = "^1.9", features = ["attributes"] }
|
async-std = { version = "^1.9", features = ["attributes"] }
|
||||||
sea-orm = { path = "../" }
|
sea-orm = { path = "../" }
|
||||||
|
|
||||||
[features]
|
|
||||||
runtime-actix-native-tls = [
|
|
||||||
"sqlx/runtime-actix-native-tls",
|
|
||||||
"sea-schema/runtime-actix-native-tls",
|
|
||||||
]
|
|
||||||
runtime-async-std-native-tls = [
|
|
||||||
"sqlx/runtime-async-std-native-tls",
|
|
||||||
"sea-schema/runtime-async-std-native-tls",
|
|
||||||
]
|
|
||||||
runtime-tokio-native-tls = [
|
|
||||||
"sqlx/runtime-tokio-native-tls",
|
|
||||||
"sea-schema/runtime-tokio-native-tls",
|
|
||||||
]
|
|
||||||
runtime-actix-rustls = [
|
|
||||||
"sqlx/runtime-actix-rustls",
|
|
||||||
"sea-schema/runtime-actix-rustls",
|
|
||||||
]
|
|
||||||
runtime-async-std-rustls = [
|
|
||||||
"sqlx/runtime-async-std-rustls",
|
|
||||||
"sea-schema/runtime-async-std-rustls",
|
|
||||||
]
|
|
||||||
runtime-tokio-rustls = [
|
|
||||||
"sqlx/runtime-tokio-rustls",
|
|
||||||
"sea-schema/runtime-tokio-rustls",
|
|
||||||
]
|
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
use crate::{EntityTransformer, Error};
|
|
||||||
use sea_schema::mysql::discovery::SchemaDiscovery;
|
|
||||||
use sqlx::MySqlPool;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct EntityGenerator {}
|
|
||||||
|
|
||||||
impl EntityGenerator {
|
|
||||||
pub async fn discover(uri: &str, schema: &str) -> Result<EntityTransformer, Error> {
|
|
||||||
let connection = MySqlPool::connect(uri).await?;
|
|
||||||
let schema_discovery = SchemaDiscovery::new(connection, schema);
|
|
||||||
let schema = schema_discovery.discover().await;
|
|
||||||
Ok(EntityTransformer { schema })
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +1,6 @@
|
|||||||
mod base_entity;
|
mod base_entity;
|
||||||
mod column;
|
mod column;
|
||||||
mod conjunct_relation;
|
mod conjunct_relation;
|
||||||
mod generator;
|
|
||||||
mod primary_key;
|
mod primary_key;
|
||||||
mod relation;
|
mod relation;
|
||||||
mod transformer;
|
mod transformer;
|
||||||
@ -10,7 +9,6 @@ mod writer;
|
|||||||
pub use base_entity::*;
|
pub use base_entity::*;
|
||||||
pub use column::*;
|
pub use column::*;
|
||||||
pub use conjunct_relation::*;
|
pub use conjunct_relation::*;
|
||||||
pub use generator::*;
|
|
||||||
pub use primary_key::*;
|
pub use primary_key::*;
|
||||||
pub use relation::*;
|
pub use relation::*;
|
||||||
pub use transformer::*;
|
pub use transformer::*;
|
||||||
|
@ -2,21 +2,17 @@ use crate::{
|
|||||||
Column, ConjunctRelation, Entity, EntityWriter, Error, PrimaryKey, Relation, RelationType,
|
Column, ConjunctRelation, Entity, EntityWriter, Error, PrimaryKey, Relation, RelationType,
|
||||||
};
|
};
|
||||||
use sea_query::TableStatement;
|
use sea_query::TableStatement;
|
||||||
use sea_schema::mysql::def::Schema;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct EntityTransformer {
|
pub struct EntityTransformer;
|
||||||
pub(crate) schema: Schema,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EntityTransformer {
|
impl EntityTransformer {
|
||||||
pub fn transform(self) -> Result<EntityWriter, Error> {
|
pub fn transform(table_stmts: Vec<TableStatement>) -> Result<EntityWriter, Error> {
|
||||||
let mut inverse_relations: HashMap<String, Vec<Relation>> = HashMap::new();
|
let mut inverse_relations: HashMap<String, Vec<Relation>> = HashMap::new();
|
||||||
let mut conjunct_relations: HashMap<String, Vec<ConjunctRelation>> = HashMap::new();
|
let mut conjunct_relations: HashMap<String, Vec<ConjunctRelation>> = HashMap::new();
|
||||||
let mut entities = HashMap::new();
|
let mut entities = HashMap::new();
|
||||||
for table_ref in self.schema.tables.iter() {
|
for table_stmt in table_stmts.into_iter() {
|
||||||
let table_stmt = table_ref.write();
|
|
||||||
let table_create = match table_stmt {
|
let table_create = match table_stmt {
|
||||||
TableStatement::Create(stmt) => stmt,
|
TableStatement::Create(stmt) => stmt,
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -1,105 +1,93 @@
|
|||||||
use crate::{Entity, Error};
|
use crate::Entity;
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use std::{
|
|
||||||
fs::{self, File},
|
|
||||||
io::{self, Write},
|
|
||||||
path::Path,
|
|
||||||
process::Command,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct EntityWriter {
|
pub struct EntityWriter {
|
||||||
pub(crate) entities: Vec<Entity>,
|
pub(crate) entities: Vec<Entity>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct WriterOutput {
|
||||||
|
pub files: Vec<OutputFile>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct OutputFile {
|
||||||
|
pub name: String,
|
||||||
|
pub content: String,
|
||||||
|
}
|
||||||
|
|
||||||
impl EntityWriter {
|
impl EntityWriter {
|
||||||
pub fn generate(self, output_dir: &str) -> Result<(), Error> {
|
pub fn generate(self) -> WriterOutput {
|
||||||
for entity in self.entities.iter() {
|
let mut files = Vec::new();
|
||||||
|
files.extend(self.write_entities());
|
||||||
|
files.push(self.write_mod());
|
||||||
|
files.push(self.write_prelude());
|
||||||
|
WriterOutput { files }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_entities(&self) -> Vec<OutputFile> {
|
||||||
|
self.entities
|
||||||
|
.iter()
|
||||||
|
.map(|entity| {
|
||||||
|
let mut lines = Vec::new();
|
||||||
|
Self::write_doc_comment(&mut lines);
|
||||||
let code_blocks = Self::gen_code_blocks(entity);
|
let code_blocks = Self::gen_code_blocks(entity);
|
||||||
Self::write(output_dir, entity, code_blocks)?;
|
Self::write(&mut lines, code_blocks);
|
||||||
|
OutputFile {
|
||||||
|
name: format!("{}.rs", entity.table_name),
|
||||||
|
content: lines.join("\n\n"),
|
||||||
}
|
}
|
||||||
for entity in self.entities.iter() {
|
})
|
||||||
Self::format_entity(output_dir, entity)?;
|
.collect()
|
||||||
}
|
|
||||||
self.write_mod(output_dir)?;
|
|
||||||
self.write_prelude(output_dir)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_mod(&self, output_dir: &str) -> io::Result<()> {
|
pub fn write_mod(&self) -> OutputFile {
|
||||||
let file_name = "mod.rs";
|
let mut lines = Vec::new();
|
||||||
let dir = Self::create_dir(output_dir)?;
|
Self::write_doc_comment(&mut lines);
|
||||||
let file_path = dir.join(file_name);
|
let code_blocks = self
|
||||||
let mut file = fs::File::create(file_path)?;
|
.entities
|
||||||
Self::write_doc_comment(&mut file)?;
|
.iter()
|
||||||
for entity in self.entities.iter() {
|
.map(|entity| Self::gen_mod(entity))
|
||||||
let code_block = Self::gen_mod(entity);
|
.collect();
|
||||||
file.write_all(code_block.to_string().as_bytes())?;
|
Self::write(&mut lines, code_blocks);
|
||||||
|
OutputFile {
|
||||||
|
name: "mod.rs".to_owned(),
|
||||||
|
content: lines.join("\n"),
|
||||||
}
|
}
|
||||||
Self::format_file(output_dir, file_name)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_prelude(&self, output_dir: &str) -> io::Result<()> {
|
pub fn write_prelude(&self) -> OutputFile {
|
||||||
let file_name = "prelude.rs";
|
let mut lines = Vec::new();
|
||||||
let dir = Self::create_dir(output_dir)?;
|
Self::write_doc_comment(&mut lines);
|
||||||
let file_path = dir.join(file_name);
|
let code_blocks = self
|
||||||
let mut file = fs::File::create(file_path)?;
|
.entities
|
||||||
Self::write_doc_comment(&mut file)?;
|
.iter()
|
||||||
for entity in self.entities.iter() {
|
.map(|entity| Self::gen_prelude_use(entity))
|
||||||
let code_block = Self::gen_prelude_use(entity);
|
.collect();
|
||||||
file.write_all(code_block.to_string().as_bytes())?;
|
Self::write(&mut lines, code_blocks);
|
||||||
|
OutputFile {
|
||||||
|
name: "prelude.rs".to_owned(),
|
||||||
|
content: lines.join("\n"),
|
||||||
}
|
}
|
||||||
Self::format_file(output_dir, file_name)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(
|
pub fn write(lines: &mut Vec<String>, code_blocks: Vec<TokenStream>) {
|
||||||
output_dir: &str,
|
lines.extend(
|
||||||
entity: &Entity,
|
code_blocks
|
||||||
code_blocks: Vec<TokenStream>,
|
.into_iter()
|
||||||
) -> io::Result<()> {
|
.map(|code_block| code_block.to_string())
|
||||||
let dir = Self::create_dir(output_dir)?;
|
.collect::<Vec<_>>(),
|
||||||
let file_path = dir.join(format!("{}.rs", entity.table_name));
|
);
|
||||||
let mut file = fs::File::create(file_path)?;
|
|
||||||
Self::write_doc_comment(&mut file)?;
|
|
||||||
for code_block in code_blocks {
|
|
||||||
file.write_all(code_block.to_string().as_bytes())?;
|
|
||||||
file.write_all(b"\n\n")?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_doc_comment(file: &mut File) -> io::Result<()> {
|
pub fn write_doc_comment(lines: &mut Vec<String>) {
|
||||||
let ver = env!("CARGO_PKG_VERSION");
|
let ver = env!("CARGO_PKG_VERSION");
|
||||||
let comments = vec![format!(
|
let comments = vec![format!(
|
||||||
"//! SeaORM Entity. Generated by sea-orm-codegen {}",
|
"//! SeaORM Entity. Generated by sea-orm-codegen {}",
|
||||||
ver
|
ver
|
||||||
)];
|
)];
|
||||||
for comment in comments {
|
lines.extend(comments);
|
||||||
file.write_all(comment.as_bytes())?;
|
lines.push("".to_owned());
|
||||||
file.write_all(b"\n\n")?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn create_dir(output_dir: &str) -> io::Result<&Path> {
|
|
||||||
let dir = Path::new(output_dir);
|
|
||||||
fs::create_dir_all(dir)?;
|
|
||||||
Ok(dir)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn format_entity(output_dir: &str, entity: &Entity) -> io::Result<()> {
|
|
||||||
Self::format_file(output_dir, &format!("{}.rs", entity.table_name))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn format_file(output_dir: &str, file_name: &str) -> io::Result<()> {
|
|
||||||
Command::new("rustfmt")
|
|
||||||
.arg(Path::new(output_dir).join(file_name))
|
|
||||||
.spawn()?
|
|
||||||
.wait()?;
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gen_code_blocks(entity: &Entity) -> Vec<TokenStream> {
|
pub fn gen_code_blocks(entity: &Entity) -> Vec<TokenStream> {
|
||||||
|
@ -3,7 +3,6 @@ use std::{error, fmt, io};
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
StdIoError(io::Error),
|
StdIoError(io::Error),
|
||||||
SqlxError(sqlx::Error),
|
|
||||||
TransformError(String),
|
TransformError(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -11,7 +10,6 @@ impl fmt::Display for Error {
|
|||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::StdIoError(e) => write!(f, "{:?}", e),
|
Self::StdIoError(e) => write!(f, "{:?}", e),
|
||||||
Self::SqlxError(e) => write!(f, "{:?}", e),
|
|
||||||
Self::TransformError(e) => write!(f, "{:?}", e),
|
Self::TransformError(e) => write!(f, "{:?}", e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -21,7 +19,6 @@ impl error::Error for Error {
|
|||||||
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
||||||
match self {
|
match self {
|
||||||
Self::StdIoError(e) => Some(e),
|
Self::StdIoError(e) => Some(e),
|
||||||
Self::SqlxError(e) => Some(e),
|
|
||||||
Self::TransformError(_) => None,
|
Self::TransformError(_) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -32,9 +29,3 @@ impl From<io::Error> for Error {
|
|||||||
Self::StdIoError(io_err)
|
Self::StdIoError(io_err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<sqlx::Error> for Error {
|
|
||||||
fn from(sqlx_err: sqlx::Error) -> Self {
|
|
||||||
Self::SqlxError(sqlx_err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user