Try Postgres enum
This commit is contained in:
parent
734608471c
commit
80c72004d1
@ -30,7 +30,7 @@ futures-util = { version = "^0.3" }
|
|||||||
log = { version = "^0.4", optional = true }
|
log = { version = "^0.4", optional = true }
|
||||||
rust_decimal = { version = "^1", optional = true }
|
rust_decimal = { version = "^1", optional = true }
|
||||||
sea-orm-macros = { version = "^0.3.0", path = "sea-orm-macros", optional = true }
|
sea-orm-macros = { version = "^0.3.0", path = "sea-orm-macros", optional = true }
|
||||||
sea-query = { version = "^0.18.0", features = ["thread-safe"] }
|
sea-query = { version = "^0.18.0", git = "https://github.com/SeaQL/sea-query.git", branch = "sea-orm/active-enum-1", features = ["thread-safe"] }
|
||||||
sea-strum = { version = "^0.21", features = ["derive", "sea-orm"] }
|
sea-strum = { version = "^0.21", features = ["derive", "sea-orm"] }
|
||||||
serde = { version = "^1.0", features = ["derive"] }
|
serde = { version = "^1.0", features = ["derive"] }
|
||||||
serde_json = { version = "^1", optional = true }
|
serde_json = { version = "^1", optional = true }
|
||||||
|
@ -71,7 +71,7 @@ use sea_query::{Nullable, Value, ValueType};
|
|||||||
/// use sea_orm::entity::prelude::*;
|
/// use sea_orm::entity::prelude::*;
|
||||||
///
|
///
|
||||||
/// // Define the `Category` active enum
|
/// // Define the `Category` active enum
|
||||||
/// #[derive(Debug, Clone, PartialEq, DeriveActiveEnum)]
|
/// #[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum)]
|
||||||
/// #[sea_orm(rs_type = "String", db_type = "String(Some(1))")]
|
/// #[sea_orm(rs_type = "String", db_type = "String(Some(1))")]
|
||||||
/// pub enum Category {
|
/// pub enum Category {
|
||||||
/// #[sea_orm(string_value = "B")]
|
/// #[sea_orm(string_value = "B")]
|
||||||
|
@ -242,6 +242,13 @@ impl ColumnType {
|
|||||||
indexed: false,
|
indexed: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn get_enum_name(&self) -> Option<&String> {
|
||||||
|
match self {
|
||||||
|
ColumnType::Enum(s) => Some(s),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ColumnDef {
|
impl ColumnDef {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
ActiveModelTrait, EntityName, EntityTrait, IntoActiveModel, Iterable, PrimaryKeyTrait,
|
ActiveModelTrait, ColumnTrait, EntityName, EntityTrait, IntoActiveModel, Iterable,
|
||||||
QueryTrait,
|
PrimaryKeyTrait, QueryTrait,
|
||||||
};
|
};
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use sea_query::{InsertStatement, ValueTuple};
|
use sea_query::{Alias, Expr, Func, InsertStatement, ValueTuple};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Insert<A>
|
pub struct Insert<A>
|
||||||
@ -124,6 +124,9 @@ where
|
|||||||
for (idx, col) in <A::Entity as EntityTrait>::Column::iter().enumerate() {
|
for (idx, col) in <A::Entity as EntityTrait>::Column::iter().enumerate() {
|
||||||
let av = am.take(col);
|
let av = am.take(col);
|
||||||
let av_has_val = av.is_set() || av.is_unchanged();
|
let av_has_val = av.is_set() || av.is_unchanged();
|
||||||
|
let col_def = col.def();
|
||||||
|
let enum_name = col_def.get_column_type().get_enum_name();
|
||||||
|
|
||||||
if columns_empty {
|
if columns_empty {
|
||||||
self.columns.push(av_has_val);
|
self.columns.push(av_has_val);
|
||||||
} else if self.columns[idx] != av_has_val {
|
} else if self.columns[idx] != av_has_val {
|
||||||
@ -131,11 +134,17 @@ where
|
|||||||
}
|
}
|
||||||
if av_has_val {
|
if av_has_val {
|
||||||
columns.push(col);
|
columns.push(col);
|
||||||
values.push(av.into_value().unwrap());
|
let val = av.into_value().unwrap();
|
||||||
|
let expr = if let Some(enum_name) = enum_name {
|
||||||
|
Func::cast_as(val, Alias::new(&enum_name))
|
||||||
|
} else {
|
||||||
|
Expr::val(val).into()
|
||||||
|
};
|
||||||
|
values.push(expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.query.columns(columns);
|
self.query.columns(columns);
|
||||||
self.query.values_panic(values);
|
self.query.exprs_panic(values);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ use crate::{ColumnTrait, EntityTrait, Iterable, QueryFilter, QueryOrder, QuerySe
|
|||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
pub use sea_query::JoinType;
|
pub use sea_query::JoinType;
|
||||||
use sea_query::{DynIden, IntoColumnRef, SeaRc, SelectStatement, SimpleExpr};
|
use sea_query::{Alias, DynIden, Expr, Func, IntoColumnRef, SeaRc, SelectStatement, SimpleExpr};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Select<E>
|
pub struct Select<E>
|
||||||
@ -109,13 +109,25 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn prepare_select(mut self) -> Self {
|
fn prepare_select(mut self) -> Self {
|
||||||
self.query.columns(self.column_list());
|
self.query.exprs(self.column_list());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn column_list(&self) -> Vec<(DynIden, E::Column)> {
|
fn column_list(&self) -> Vec<SimpleExpr> {
|
||||||
let table = SeaRc::new(E::default()) as DynIden;
|
let table = SeaRc::new(E::default()) as DynIden;
|
||||||
E::Column::iter().map(|col| (table.clone(), col)).collect()
|
E::Column::iter()
|
||||||
|
.map(|col| {
|
||||||
|
let col_def = col.def();
|
||||||
|
let enum_name = col_def.get_column_type().get_enum_name();
|
||||||
|
let col_expr = Expr::tbl(table.clone(), col);
|
||||||
|
let col_expr = if let Some(_) = enum_name {
|
||||||
|
Func::cast_expr_as(col_expr, Alias::new("text"))
|
||||||
|
} else {
|
||||||
|
col_expr.into()
|
||||||
|
};
|
||||||
|
col_expr
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare_from(mut self) -> Self {
|
fn prepare_from(mut self) -> Self {
|
||||||
|
@ -3,7 +3,7 @@ use crate::{
|
|||||||
QueryTrait,
|
QueryTrait,
|
||||||
};
|
};
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use sea_query::{IntoIden, SimpleExpr, UpdateStatement};
|
use sea_query::{Alias, Expr, Func, IntoIden, SimpleExpr, UpdateStatement};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Update;
|
pub struct Update;
|
||||||
@ -104,9 +104,17 @@ where
|
|||||||
if <A::Entity as EntityTrait>::PrimaryKey::from_column(col).is_some() {
|
if <A::Entity as EntityTrait>::PrimaryKey::from_column(col).is_some() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
let col_def = col.def();
|
||||||
|
let enum_name = col_def.get_column_type().get_enum_name();
|
||||||
let av = self.model.get(col);
|
let av = self.model.get(col);
|
||||||
if av.is_set() {
|
if av.is_set() {
|
||||||
self.query.value(col, av.unwrap());
|
let val = av.into_value().unwrap();
|
||||||
|
let expr = if let Some(enum_name) = enum_name {
|
||||||
|
Func::cast_as(val, Alias::new(&enum_name))
|
||||||
|
} else {
|
||||||
|
Expr::val(val).into()
|
||||||
|
};
|
||||||
|
self.query.value_expr(col, expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
|
@ -40,7 +40,7 @@ pub async fn insert_active_enum(db: &DatabaseConnection) -> Result<(), DbErr> {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
ActiveModel {
|
let am = ActiveModel {
|
||||||
category: Set(Some(Category::Big)),
|
category: Set(Some(Category::Big)),
|
||||||
color: Set(Some(Color::Black)),
|
color: Set(Some(Color::Black)),
|
||||||
tea: Set(Some(Tea::EverydayTea)),
|
tea: Set(Some(Tea::EverydayTea)),
|
||||||
@ -59,5 +59,10 @@ pub async fn insert_active_enum(db: &DatabaseConnection) -> Result<(), DbErr> {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let res = am.delete(db).await?;
|
||||||
|
|
||||||
|
assert_eq!(res.rows_affected, 1);
|
||||||
|
assert_eq!(Entity::find().one(db).await?, None);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ pub use super::super::bakery_chain::*;
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::common::setup::create_table;
|
use crate::common::setup::create_table;
|
||||||
use sea_orm::{error::*, sea_query, DatabaseConnection, DbConn, ExecResult};
|
use sea_orm::{error::*, sea_query, DatabaseConnection, DbConn, ExecResult};
|
||||||
use sea_query::{ColumnDef, ForeignKeyCreateStatement};
|
use sea_query::{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?;
|
||||||
@ -103,6 +103,8 @@ pub async fn create_self_join_table(db: &DbConn) -> Result<ExecResult, DbErr> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create_active_enum_table(db: &DbConn) -> Result<ExecResult, DbErr> {
|
pub async fn create_active_enum_table(db: &DbConn) -> Result<ExecResult, DbErr> {
|
||||||
|
let tea_enum = Alias::new("tea");
|
||||||
|
|
||||||
let stmt = sea_query::Table::create()
|
let stmt = sea_query::Table::create()
|
||||||
.table(active_enum::Entity)
|
.table(active_enum::Entity)
|
||||||
.col(
|
.col(
|
||||||
@ -114,8 +116,45 @@ pub async fn create_active_enum_table(db: &DbConn) -> Result<ExecResult, DbErr>
|
|||||||
)
|
)
|
||||||
.col(ColumnDef::new(active_enum::Column::Category).string_len(1))
|
.col(ColumnDef::new(active_enum::Column::Category).string_len(1))
|
||||||
.col(ColumnDef::new(active_enum::Column::Color).integer())
|
.col(ColumnDef::new(active_enum::Column::Color).integer())
|
||||||
// .col(ColumnDef::new(active_enum::Column::Tea).custom(Alias::new("tea")))
|
.col(ColumnDef::new(active_enum::Column::Tea).custom(tea_enum.clone()))
|
||||||
.to_owned();
|
.to_owned();
|
||||||
|
|
||||||
|
match db {
|
||||||
|
#[cfg(feature = "sqlx-postgres")]
|
||||||
|
DatabaseConnection::SqlxPostgresPoolConnection(_) => {
|
||||||
|
use sea_orm::{ConnectionTrait, Statement};
|
||||||
|
use sea_query::{extension::postgres::Type, PostgresQueryBuilder};
|
||||||
|
|
||||||
|
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
|
create_table(db, &stmt, ActiveEnum).await
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user