Add create_enum_from_entity
This commit is contained in:
parent
e04495b94d
commit
55de1968bb
@ -73,6 +73,15 @@ macro_rules! build_any_stmt {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! build_postgres_stmt {
|
||||||
|
($stmt: expr, $db_backend: expr) => {
|
||||||
|
match $db_backend {
|
||||||
|
DbBackend::Postgres => $stmt.to_string(PostgresQueryBuilder),
|
||||||
|
DbBackend::MySql | DbBackend::Sqlite => unimplemented!(),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! build_query_stmt {
|
macro_rules! build_query_stmt {
|
||||||
($stmt: ty) => {
|
($stmt: ty) => {
|
||||||
impl StatementBuilder for $stmt {
|
impl StatementBuilder for $stmt {
|
||||||
@ -105,3 +114,18 @@ build_schema_stmt!(sea_query::TableDropStatement);
|
|||||||
build_schema_stmt!(sea_query::TableAlterStatement);
|
build_schema_stmt!(sea_query::TableAlterStatement);
|
||||||
build_schema_stmt!(sea_query::TableRenameStatement);
|
build_schema_stmt!(sea_query::TableRenameStatement);
|
||||||
build_schema_stmt!(sea_query::TableTruncateStatement);
|
build_schema_stmt!(sea_query::TableTruncateStatement);
|
||||||
|
|
||||||
|
macro_rules! build_type_stmt {
|
||||||
|
($stmt: ty) => {
|
||||||
|
impl StatementBuilder for $stmt {
|
||||||
|
fn build(&self, db_backend: &DbBackend) -> Statement {
|
||||||
|
let stmt = build_postgres_stmt!(self, db_backend);
|
||||||
|
Statement::from_string(*db_backend, stmt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
build_type_stmt!(sea_query::extension::postgres::TypeAlterStatement);
|
||||||
|
build_type_stmt!(sea_query::extension::postgres::TypeCreateStatement);
|
||||||
|
build_type_stmt!(sea_query::extension::postgres::TypeDropStatement);
|
||||||
|
@ -2,9 +2,19 @@ use crate::{
|
|||||||
unpack_table_ref, ColumnTrait, ColumnType, DbBackend, EntityTrait, Identity, Iterable,
|
unpack_table_ref, ColumnTrait, ColumnType, DbBackend, EntityTrait, Identity, Iterable,
|
||||||
PrimaryKeyToColumn, PrimaryKeyTrait, RelationTrait, Schema,
|
PrimaryKeyToColumn, PrimaryKeyTrait, RelationTrait, Schema,
|
||||||
};
|
};
|
||||||
use sea_query::{ColumnDef, ForeignKeyCreateStatement, Iden, Index, TableCreateStatement};
|
use sea_query::{
|
||||||
|
extension::postgres::{Type, TypeCreateStatement},
|
||||||
|
Alias, ColumnDef, ForeignKeyCreateStatement, Iden, Index, TableCreateStatement,
|
||||||
|
};
|
||||||
|
|
||||||
impl Schema {
|
impl Schema {
|
||||||
|
pub fn create_enum_from_entity<E>(entity: E, db_backend: DbBackend) -> Vec<TypeCreateStatement>
|
||||||
|
where
|
||||||
|
E: EntityTrait,
|
||||||
|
{
|
||||||
|
create_enum_from_entity(entity, db_backend)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_table_from_entity<E>(entity: E, db_backend: DbBackend) -> TableCreateStatement
|
pub fn create_table_from_entity<E>(entity: E, db_backend: DbBackend) -> TableCreateStatement
|
||||||
where
|
where
|
||||||
E: EntityTrait,
|
E: EntityTrait,
|
||||||
@ -13,6 +23,33 @@ impl Schema {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn create_enum_from_entity<E>(_: E, db_backend: DbBackend) -> Vec<TypeCreateStatement>
|
||||||
|
where
|
||||||
|
E: EntityTrait,
|
||||||
|
{
|
||||||
|
if matches!(db_backend, DbBackend::MySql | DbBackend::Sqlite) {
|
||||||
|
return Vec::new();
|
||||||
|
}
|
||||||
|
let mut vec = Vec::new();
|
||||||
|
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, values) = match col_type {
|
||||||
|
ColumnType::Enum(s, v) => (s.as_str(), v),
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
let stmt = Type::create()
|
||||||
|
.as_enum(Alias::new(name))
|
||||||
|
.values(values.into_iter().map(|val| Alias::new(val.as_str())))
|
||||||
|
.to_owned();
|
||||||
|
vec.push(stmt);
|
||||||
|
}
|
||||||
|
vec
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn create_table_from_entity<E>(entity: E, db_backend: DbBackend) -> TableCreateStatement
|
pub(crate) fn create_table_from_entity<E>(entity: E, db_backend: DbBackend) -> TableCreateStatement
|
||||||
where
|
where
|
||||||
E: EntityTrait,
|
E: EntityTrait,
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
pub use super::super::bakery_chain::*;
|
pub use super::super::bakery_chain::*;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::common::setup::create_table;
|
use crate::{common::setup::create_table, create_enum};
|
||||||
use sea_orm::{
|
use sea_orm::{
|
||||||
error::*, sea_query, ConnectionTrait, DatabaseConnection, DbBackend, DbConn, ExecResult,
|
error::*, sea_query, ConnectionTrait, DatabaseConnection, DbBackend, DbConn, ExecResult,
|
||||||
Statement,
|
|
||||||
};
|
|
||||||
use sea_query::{
|
|
||||||
extension::postgres::Type, Alias, ColumnDef, ForeignKeyCreateStatement, PostgresQueryBuilder,
|
|
||||||
};
|
};
|
||||||
|
use sea_query::{extension::postgres::Type, Alias, ColumnDef, ForeignKeyCreateStatement};
|
||||||
|
|
||||||
pub async fn create_tables(db: &DatabaseConnection) -> Result<(), DbErr> {
|
pub async fn create_tables(db: &DatabaseConnection) -> Result<(), DbErr> {
|
||||||
create_log_table(db).await?;
|
create_log_table(db).await?;
|
||||||
@ -111,14 +108,23 @@ pub async fn create_active_enum_table(db: &DbConn) -> Result<ExecResult, DbErr>
|
|||||||
let db_backend = db.get_database_backend();
|
let db_backend = db.get_database_backend();
|
||||||
let tea_enum = Alias::new("tea");
|
let tea_enum = Alias::new("tea");
|
||||||
|
|
||||||
|
let create_enum_stmts = match db_backend {
|
||||||
|
DbBackend::MySql | DbBackend::Sqlite => Vec::new(),
|
||||||
|
DbBackend::Postgres => vec![Type::create()
|
||||||
|
.as_enum(tea_enum.clone())
|
||||||
|
.values(vec![Alias::new("EverydayTea"), Alias::new("BreakfastTea")])
|
||||||
|
.to_owned()],
|
||||||
|
};
|
||||||
|
|
||||||
|
create_enum(db, &create_enum_stmts, ActiveEnum).await?;
|
||||||
|
|
||||||
let mut tea_col = ColumnDef::new(active_enum::Column::Tea);
|
let mut tea_col = ColumnDef::new(active_enum::Column::Tea);
|
||||||
match db_backend {
|
match db_backend {
|
||||||
DbBackend::MySql => tea_col.custom(Alias::new("ENUM('EverydayTea', 'BreakfastTea')")),
|
DbBackend::MySql => tea_col.custom(Alias::new("ENUM('EverydayTea', 'BreakfastTea')")),
|
||||||
DbBackend::Postgres => tea_col.custom(tea_enum.clone()),
|
|
||||||
DbBackend::Sqlite => tea_col.text(),
|
DbBackend::Sqlite => tea_col.text(),
|
||||||
|
DbBackend::Postgres => tea_col.custom(tea_enum),
|
||||||
};
|
};
|
||||||
|
let create_table_stmt = sea_query::Table::create()
|
||||||
let stmt = sea_query::Table::create()
|
|
||||||
.table(active_enum::Entity)
|
.table(active_enum::Entity)
|
||||||
.col(
|
.col(
|
||||||
ColumnDef::new(active_enum::Column::Id)
|
ColumnDef::new(active_enum::Column::Id)
|
||||||
@ -132,32 +138,5 @@ pub async fn create_active_enum_table(db: &DbConn) -> Result<ExecResult, DbErr>
|
|||||||
.col(&mut tea_col)
|
.col(&mut tea_col)
|
||||||
.to_owned();
|
.to_owned();
|
||||||
|
|
||||||
if db_backend == DbBackend::Postgres {
|
create_table(db, &create_table_stmt, ActiveEnum).await
|
||||||
let drop_type_stmt = Type::drop()
|
|
||||||
.name(tea_enum.clone())
|
|
||||||
.cascade()
|
|
||||||
.if_exists()
|
|
||||||
.to_owned();
|
|
||||||
let (sql, values) = drop_type_stmt.build(PostgresQueryBuilder);
|
|
||||||
let stmt = Statement::from_sql_and_values(db.get_database_backend(), &sql, values);
|
|
||||||
db.execute(stmt).await?;
|
|
||||||
|
|
||||||
let create_type_stmt = Type::create()
|
|
||||||
.as_enum(tea_enum)
|
|
||||||
.values(vec![Alias::new("EverydayTea"), Alias::new("BreakfastTea")])
|
|
||||||
.to_owned();
|
|
||||||
// FIXME: This is not working
|
|
||||||
{
|
|
||||||
let (sql, values) = create_type_stmt.build(PostgresQueryBuilder);
|
|
||||||
let _stmt = Statement::from_sql_and_values(db.get_database_backend(), &sql, values);
|
|
||||||
}
|
|
||||||
// But this is working...
|
|
||||||
let stmt = Statement::from_string(
|
|
||||||
db.get_database_backend(),
|
|
||||||
create_type_stmt.to_string(PostgresQueryBuilder),
|
|
||||||
);
|
|
||||||
db.execute(stmt).await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
create_table(db, &stmt, ActiveEnum).await
|
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
use sea_orm::{
|
use sea_orm::{
|
||||||
ConnectionTrait, Database, DatabaseBackend, DatabaseConnection, DbBackend, DbConn, DbErr,
|
ColumnTrait, ColumnType, ConnectionTrait, Database, DatabaseBackend, DatabaseConnection,
|
||||||
EntityTrait, ExecResult, Schema, Statement,
|
DbBackend, DbConn, DbErr, EntityTrait, ExecResult, Iterable, Schema, Statement,
|
||||||
|
};
|
||||||
|
use sea_query::{
|
||||||
|
extension::postgres::{Type, TypeCreateStatement},
|
||||||
|
Alias, Table, TableCreateStatement,
|
||||||
};
|
};
|
||||||
use sea_query::{Alias, Table, TableCreateStatement};
|
|
||||||
|
|
||||||
pub async fn setup(base_url: &str, db_name: &str) -> DatabaseConnection {
|
pub async fn setup(base_url: &str, db_name: &str) -> DatabaseConnection {
|
||||||
let db = if cfg!(feature = "sqlx-mysql") {
|
let db = if cfg!(feature = "sqlx-mysql") {
|
||||||
@ -74,6 +77,52 @@ pub async fn tear_down(base_url: &str, db_name: &str) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(s, _) => s.as_str(),
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
let drop_type_stmt = Type::drop()
|
||||||
|
.name(Alias::new(name))
|
||||||
|
.if_exists()
|
||||||
|
.cascade()
|
||||||
|
.to_owned();
|
||||||
|
let stmt = builder.build(&drop_type_stmt);
|
||||||
|
db.execute(stmt).await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let expect_stmts: Vec<Statement> = creates.iter().map(|stmt| builder.build(stmt)).collect();
|
||||||
|
let create_from_entity_stmts: Vec<Statement> =
|
||||||
|
Schema::create_enum_from_entity(entity, db.get_database_backend())
|
||||||
|
.iter()
|
||||||
|
.map(|stmt| builder.build(stmt))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
assert_eq!(expect_stmts, create_from_entity_stmts);
|
||||||
|
|
||||||
|
for stmt in expect_stmts {
|
||||||
|
db.execute(stmt).await.map(|_| ())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn create_table<E>(
|
pub async fn create_table<E>(
|
||||||
db: &DbConn,
|
db: &DbConn,
|
||||||
create: &TableCreateStatement,
|
create: &TableCreateStatement,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user