Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite enum and text casting #973

Merged
merged 3 commits into from
Sep 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 8 additions & 9 deletions src/entity/column.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{EntityName, IdenStatic, Iterable};
use sea_query::{Alias, BinOper, DynIden, Expr, SeaRc, SelectStatement, SimpleExpr, Value};
use crate::{cast_text_as_enum, EntityName, IdenStatic, IntoSimpleExpr, Iterable};
use sea_query::{BinOper, DynIden, Expr, SeaRc, SelectStatement, SimpleExpr, Value};
use std::str::FromStr;

/// Defines a Column for an Entity
Expand Down Expand Up @@ -100,13 +100,7 @@ macro_rules! bind_oper_with_enum_casting {
where
V: Into<Value>,
{
let val = Expr::val(v);
let col_def = self.def();
let col_type = col_def.get_column_type();
let expr = match col_type.get_enum_name() {
Some(enum_name) => val.as_enum(Alias::new(enum_name)),
None => val.into(),
};
let expr = cast_text_as_enum(Expr::val(v), self);
Expr::tbl(self.entity_name(), *self).binary(BinOper::$bin_op, expr)
}
};
Expand Down Expand Up @@ -305,6 +299,11 @@ pub trait ColumnTrait: IdenStatic + Iterable + FromStr {

bind_subquery_func!(in_subquery);
bind_subquery_func!(not_in_subquery);

/// Construct a [`SimpleExpr::Column`] wrapped in [`Expr`].
fn into_expr(self) -> Expr {
Expr::expr(self.into_simple_expr())
}
}

impl ColumnType {
Expand Down
22 changes: 7 additions & 15 deletions src/executor/insert.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
use crate::{
error::*, ActiveModelTrait, ColumnTrait, ConnectionTrait, EntityTrait, Insert, IntoActiveModel,
Iterable, PrimaryKeyTrait, SelectModel, SelectorRaw, Statement, TryFromU64,
};
use sea_query::{
Alias, Expr, FromValueTuple, Iden, InsertStatement, IntoColumnRef, Query, ValueTuple,
cast_enum_as_text, error::*, ActiveModelTrait, ConnectionTrait, EntityTrait, Insert,
IntoActiveModel, Iterable, PrimaryKeyTrait, SelectModel, SelectorRaw, Statement, TryFromU64,
};
use sea_query::{Expr, FromValueTuple, Iden, InsertStatement, IntoColumnRef, Query, ValueTuple};
use std::{future::Future, marker::PhantomData};

/// Defines a structure to perform INSERT operations in an ActiveModel
Expand Down Expand Up @@ -149,16 +147,10 @@ where
let db_backend = db.get_database_backend();
let found = match db.support_returning() {
true => {
let returning =
Query::returning().exprs(<A::Entity as EntityTrait>::Column::iter().map(|c| {
let col = Expr::col(c);
let col_def = ColumnTrait::def(&c);
let col_type = col_def.get_column_type();
match col_type.get_enum_name() {
Some(_) => col.as_enum(Alias::new("text")),
None => col.into(),
}
}));
let returning = Query::returning().exprs(
<A::Entity as EntityTrait>::Column::iter()
.map(|c| cast_enum_as_text(Expr::col(c), &c)),
);
insert_statement.returning(returning);
SelectorRaw::<SelectModel<<A::Entity as EntityTrait>::Model>>::from_statement(
db_backend.build(&insert_statement),
Expand Down
18 changes: 6 additions & 12 deletions src/executor/update.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::{
error::*, ActiveModelTrait, ColumnTrait, ConnectionTrait, EntityTrait, IntoActiveModel,
cast_enum_as_text, error::*, ActiveModelTrait, ConnectionTrait, EntityTrait, IntoActiveModel,
Iterable, SelectModel, SelectorRaw, Statement, UpdateMany, UpdateOne,
};
use sea_query::{Alias, Expr, FromValueTuple, Query, UpdateStatement};
use sea_query::{Expr, FromValueTuple, Query, UpdateStatement};
use std::future::Future;

/// Defines an update operation
Expand Down Expand Up @@ -91,16 +91,10 @@ where
{
match db.support_returning() {
true => {
let returning =
Query::returning().exprs(<A::Entity as EntityTrait>::Column::iter().map(|c| {
let col = Expr::col(c);
let col_def = c.def();
let col_type = col_def.get_column_type();
match col_type.get_enum_name() {
Some(_) => col.as_enum(Alias::new("text")),
None => col.into(),
}
}));
let returning = Query::returning().exprs(
<A::Entity as EntityTrait>::Column::iter()
.map(|c| cast_enum_as_text(Expr::col(c), &c)),
);
query.returning(returning);
let db_backend = db.get_database_backend();
let found: Option<<A::Entity as EntityTrait>::Model> =
Expand Down
18 changes: 4 additions & 14 deletions src/query/combine.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
use crate::{
ColumnTrait, EntityTrait, IdenStatic, IntoSimpleExpr, Iterable, QueryTrait, Select, SelectTwo,
SelectTwoMany,
cast_enum_as_text, ColumnTrait, EntityTrait, IdenStatic, Iterable, QueryTrait, Select,
SelectTwo, SelectTwoMany,
};
use core::marker::PhantomData;
pub use sea_query::JoinType;
use sea_query::{
Alias, ColumnRef, DynIden, Expr, Iden, Order, SeaRc, SelectExpr, SelectStatement, SimpleExpr,
};
use sea_query::{Alias, ColumnRef, Iden, Order, SeaRc, SelectExpr, SelectStatement, SimpleExpr};

macro_rules! select_def {
( $ident: ident, $str: expr ) => {
Expand Down Expand Up @@ -148,18 +146,10 @@ where
F: EntityTrait,
S: QueryTrait<QueryStatement = SelectStatement>,
{
let text_type = SeaRc::new(Alias::new("text")) as DynIden;
for col in <F::Column as Iterable>::iter() {
let col_def = col.def();
let col_type = col_def.get_column_type();
let alias = format!("{}{}", SelectB.as_str(), col.as_str());
let expr = Expr::expr(col.into_simple_expr());
let expr = match col_type.get_enum_name() {
Some(_) => expr.as_enum(text_type.clone()),
None => expr.into(),
};
selector.query().expr(SelectExpr {
expr,
expr: cast_enum_as_text(col.into_expr(), &col),
alias: Some(SeaRc::new(Alias::new(&alias))),
window: None,
});
Expand Down
55 changes: 54 additions & 1 deletion src/query/helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,34 @@ pub trait QuerySelect: Sized {
/// r#"SELECT "cake"."name" FROM "cake""#
/// );
/// ```
///
/// Enum column will be casted into text (PostgreSQL only)
///
/// ```
/// use sea_orm::{entity::*, query::*, tests_cfg::lunch_set, DbBackend};
///
/// assert_eq!(
/// lunch_set::Entity::find()
/// .select_only()
/// .column(lunch_set::Column::Tea)
/// .build(DbBackend::Postgres)
/// .to_string(),
/// r#"SELECT CAST("lunch_set"."tea" AS text) FROM "lunch_set""#
/// );
/// assert_eq!(
/// lunch_set::Entity::find()
/// .select_only()
/// .column(lunch_set::Column::Tea)
/// .build(DbBackend::MySql)
/// .to_string(),
/// r#"SELECT `lunch_set`.`tea` FROM `lunch_set`"#
/// );
/// ```
fn column<C>(mut self, col: C) -> Self
where
C: ColumnTrait,
{
self.query().expr(col.into_simple_expr());
self.query().expr(cast_enum_as_text(col.into_expr(), &col));
self
}

Expand Down Expand Up @@ -532,3 +555,33 @@ pub(crate) fn unpack_table_alias(table_ref: &TableRef) -> Option<DynIden> {
| TableRef::DatabaseSchemaTableAlias(_, _, _, alias) => Some(SeaRc::clone(alias)),
}
}

#[derive(Iden)]
struct Text;

pub(crate) fn cast_enum_as_text<C>(expr: Expr, col: &C) -> SimpleExpr
where
C: ColumnTrait,
{
cast_enum_text_inner(expr, col, |col, _| col.as_enum(Text))
}

pub(crate) fn cast_text_as_enum<C>(expr: Expr, col: &C) -> SimpleExpr
where
C: ColumnTrait,
{
cast_enum_text_inner(expr, col, |col, enum_name| col.as_enum(enum_name))
}

fn cast_enum_text_inner<C, F>(expr: Expr, col: &C, f: F) -> SimpleExpr
billy1624 marked this conversation as resolved.
Show resolved Hide resolved
where
C: ColumnTrait,
F: Fn(Expr, DynIden) -> SimpleExpr,
{
let col_def = col.def();
let col_type = col_def.get_column_type();
match col_type.get_enum_name() {
Some(enum_name) => f(expr, SeaRc::new(Alias::new(enum_name))),
None => expr.into(),
}
}
13 changes: 3 additions & 10 deletions src/query/insert.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use crate::{
ActiveModelTrait, ColumnTrait, EntityName, EntityTrait, IntoActiveModel, Iterable,
cast_text_as_enum, ActiveModelTrait, EntityName, EntityTrait, IntoActiveModel, Iterable,
PrimaryKeyTrait, QueryTrait,
};
use core::marker::PhantomData;
use sea_query::{Alias, Expr, InsertStatement, OnConflict, ValueTuple};
use sea_query::{Expr, InsertStatement, OnConflict, ValueTuple};

/// Performs INSERT operations on a ActiveModel
#[derive(Debug)]
Expand Down Expand Up @@ -134,14 +134,7 @@ where
}
if av_has_val {
columns.push(col);
let val = Expr::val(av.into_value().unwrap());
let col_def = col.def();
let col_type = col_def.get_column_type();
let expr = match col_type.get_enum_name() {
Some(enum_name) => val.as_enum(Alias::new(enum_name)),
None => val.into(),
};
values.push(expr);
values.push(cast_text_as_enum(Expr::val(av.into_value().unwrap()), &col));
}
}
self.query.columns(columns);
Expand Down
13 changes: 3 additions & 10 deletions src/query/join.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use crate::{
join_tbl_on_condition, unpack_table_ref, ColumnTrait, EntityTrait, IdenStatic, Iterable,
cast_enum_as_text, join_tbl_on_condition, unpack_table_ref, EntityTrait, IdenStatic, Iterable,
Linked, QuerySelect, Related, Select, SelectA, SelectB, SelectTwo, SelectTwoMany,
};
pub use sea_query::JoinType;
use sea_query::{Alias, Condition, DynIden, Expr, IntoIden, SeaRc, SelectExpr};
use sea_query::{Alias, Condition, Expr, IntoIden, SeaRc, SelectExpr};

impl<E> Select<E>
where
Expand Down Expand Up @@ -92,22 +92,15 @@ where
.join_as(JoinType::LeftJoin, table_ref, to_tbl, condition);
}
slf = slf.apply_alias(SelectA.as_str());
let text_type = SeaRc::new(Alias::new("text")) as DynIden;
let mut select_two = SelectTwo::new_without_prepare(slf.query);
for col in <T::Column as Iterable>::iter() {
let col_def = col.def();
let col_type = col_def.get_column_type();
let alias = format!("{}{}", SelectB.as_str(), col.as_str());
let expr = Expr::tbl(
Alias::new(&format!("r{}", l.link().len() - 1)).into_iden(),
col.into_iden(),
);
let expr = match col_type.get_enum_name() {
Some(_) => expr.as_enum(text_type.clone()),
None => expr.into(),
};
select_two.query().expr(SelectExpr {
expr,
expr: cast_enum_as_text(expr, &col),
alias: Some(SeaRc::new(Alias::new(&alias))),
window: None,
});
Expand Down
19 changes: 6 additions & 13 deletions src/query/select.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
use crate::{ColumnTrait, EntityTrait, Iterable, QueryFilter, QueryOrder, QuerySelect, QueryTrait};
use crate::{
cast_enum_as_text, ColumnTrait, EntityTrait, Iterable, QueryFilter, QueryOrder, QuerySelect,
QueryTrait,
};
use core::fmt::Debug;
use core::marker::PhantomData;
pub use sea_query::JoinType;
use sea_query::{Alias, DynIden, Expr, IntoColumnRef, SeaRc, SelectStatement, SimpleExpr};
use sea_query::{IntoColumnRef, SelectStatement, SimpleExpr};

/// Defines a structure to perform select operations
#[derive(Clone, Debug)]
Expand Down Expand Up @@ -119,18 +122,8 @@ where
}

fn column_list(&self) -> Vec<SimpleExpr> {
let table = SeaRc::new(E::default()) as DynIden;
let text_type = SeaRc::new(Alias::new("text")) as DynIden;
E::Column::iter()
.map(|col| {
let expr = Expr::tbl(table.clone(), col);
let col_def = col.def();
let col_type = col_def.get_column_type();
match col_type.get_enum_name() {
Some(_) => expr.as_enum(text_type.clone()),
None => expr.into(),
}
})
.map(|col| cast_enum_as_text(col.into_expr(), &col))
.collect()
}

Expand Down
14 changes: 4 additions & 10 deletions src/query/update.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use crate::{
ActiveModelTrait, ColumnTrait, EntityTrait, Iterable, PrimaryKeyToColumn, QueryFilter,
QueryTrait,
cast_text_as_enum, ActiveModelTrait, ColumnTrait, EntityTrait, Iterable, PrimaryKeyToColumn,
QueryFilter, QueryTrait,
};
use core::marker::PhantomData;
use sea_query::{Alias, Expr, IntoIden, SimpleExpr, UpdateStatement};
use sea_query::{Expr, IntoIden, SimpleExpr, UpdateStatement};

/// Defines a structure to perform UPDATE query operations on a ActiveModel
#[derive(Clone, Debug)]
Expand Down Expand Up @@ -109,13 +109,7 @@ where
}
let av = self.model.get(col);
if av.is_set() {
let val = Expr::val(av.into_value().unwrap());
let col_def = col.def();
let col_type = col_def.get_column_type();
let expr = match col_type.get_enum_name() {
Some(enum_name) => val.as_enum(Alias::new(enum_name)),
None => val.into(),
};
let expr = cast_text_as_enum(Expr::val(av.into_value().unwrap()), &col);
self.query.value_expr(col, expr);
}
}
Expand Down
23 changes: 23 additions & 0 deletions src/tests_cfg/lunch_set.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use super::sea_orm_active_enums::*;
use crate as sea_orm;
use crate::entity::prelude::*;

#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "lunch_set")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub name: String,
pub tea: Tea,
}

#[derive(Copy, Clone, Debug, EnumIter)]
pub enum Relation {}

impl RelationTrait for Relation {
fn def(&self) -> RelationDef {
panic!("No RelationDef")
}
}

impl ActiveModelBehavior for ActiveModel {}
3 changes: 3 additions & 0 deletions src/tests_cfg/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ pub mod entity_linked;
pub mod filling;
pub mod fruit;
pub mod indexes;
pub mod lunch_set;
pub mod rust_keyword;
pub mod sea_orm_active_enums;
pub mod vendor;

pub use cake::Entity as Cake;
Expand All @@ -17,5 +19,6 @@ pub use cake_filling::Entity as CakeFilling;
pub use cake_filling_price::Entity as CakeFillingPrice;
pub use filling::Entity as Filling;
pub use fruit::Entity as Fruit;
pub use lunch_set::Entity as LunchSet;
pub use rust_keyword::Entity as RustKeyword;
pub use vendor::Entity as Vendor;
11 changes: 11 additions & 0 deletions src/tests_cfg/sea_orm_active_enums.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use crate as sea_orm;
use crate::entity::prelude::*;

#[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum)]
#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "tea")]
pub enum Tea {
#[sea_orm(string_value = "EverydayTea")]
EverydayTea,
#[sea_orm(string_value = "BreakfastTea")]
BreakfastTea,
}