1use crate::{
2 ColumnDef, ColumnType, DbBackend, EntityName, Iden, IdenStatic, IntoSimpleExpr, Iterable,
3};
4use sea_query::{
5 BinOper, DynIden, Expr, ExprTrait, IntoIden, IntoLikeExpr, SeaRc, SelectStatement, Value,
6};
7use std::{borrow::Cow, str::FromStr};
8
9mod types;
10pub use types::*;
11
12pub(crate) mod macros {
13 macro_rules! bind_oper {
14 ($vis:vis $op:ident, $bin_op:ident) => {
15 #[allow(missing_docs)]
16 $vis fn $op<V>(&self, v: V) -> Expr
17 where
18 V: Into<Value>,
19 {
20 let expr = self.save_as(Expr::val(v));
21 Expr::col(self.as_column_ref()).binary(BinOper::$bin_op, expr)
22 }
23 };
24 }
25
26 macro_rules! bind_func_no_params {
27 ($vis:vis $func:ident) => {
28 $vis fn $func(&self) -> Expr {
30 Expr::col(self.as_column_ref()).$func()
31 }
32 };
33 }
34
35 macro_rules! bind_vec_func {
36 ($vis:vis $func:ident) => {
37 #[allow(missing_docs)]
38 #[allow(clippy::wrong_self_convention)]
39 $vis fn $func<V, I>(&self, v: I) -> Expr
40 where
41 V: Into<Value>,
42 I: IntoIterator<Item = V>,
43 {
44 let v_with_enum_cast = v.into_iter().map(|v| self.save_as(Expr::val(v)));
45 Expr::col(self.as_column_ref()).$func(v_with_enum_cast)
46 }
47 };
48 }
49
50 macro_rules! bind_subquery_func {
51 ($vis:vis $func:ident) => {
52 #[allow(clippy::wrong_self_convention)]
53 #[allow(missing_docs)]
54 $vis fn $func(&self, s: SelectStatement) -> Expr {
55 Expr::col(self.as_column_ref()).$func(s)
56 }
57 };
58 }
59
60 macro_rules! bind_array_oper {
61 ($vis:vis $op:ident, $oper:ident) => {
62 #[cfg(feature = "postgres-array")]
63 $vis fn $op<V, I>(&self, v: I) -> Expr
65 where
66 V: Into<Value> + sea_query::ValueType + sea_query::postgres_array::NotU8,
67 I: IntoIterator<Item = V>,
68 {
69 use sea_query::extension::postgres::PgBinOper;
70
71 let vec: Vec<_> = v.into_iter().collect();
72 Expr::col(self.as_column_ref()).binary(PgBinOper::$oper, self.save_as(Expr::val(vec)))
73 }
74 };
75 }
76
77 pub(crate) use bind_array_oper;
78 pub(crate) use bind_func_no_params;
79 pub(crate) use bind_oper;
80 pub(crate) use bind_subquery_func;
81 pub(crate) use bind_vec_func;
82}
83
84use macros::*;
85
86pub trait ColumnTrait: IdenStatic + Iterable + FromStr {
88 #[allow(missing_docs)]
89 type EntityName: EntityName;
90
91 fn def(&self) -> ColumnDef;
93
94 fn enum_type_name(&self) -> Option<&'static str> {
96 None
97 }
98
99 fn entity_name(&self) -> DynIden {
101 SeaRc::new(Self::EntityName::default())
102 }
103
104 fn as_column_ref(&self) -> (DynIden, DynIden) {
106 (self.entity_name(), SeaRc::new(*self))
107 }
108
109 fn eq<V>(&self, v: V) -> Expr
129 where
130 V: Into<Value>,
131 {
132 let v = v.into();
133 if v == v.as_null() {
134 Expr::col(self.as_column_ref()).is_null()
135 } else {
136 let expr = self.save_as(Expr::val(v));
137 Expr::col(self.as_column_ref()).eq(expr)
138 }
139 }
140
141 fn ne<V>(&self, v: V) -> Expr
161 where
162 V: Into<Value>,
163 {
164 let v = v.into();
165 if v == v.as_null() {
166 Expr::col(self.as_column_ref()).is_not_null()
167 } else {
168 let expr = self.save_as(Expr::val(v));
169 Expr::col(self.as_column_ref()).ne(expr)
170 }
171 }
172
173 bind_oper!(gt, GreaterThan);
174 bind_oper!(gte, GreaterThanOrEqual);
175 bind_oper!(lt, SmallerThan);
176 bind_oper!(lte, SmallerThanOrEqual);
177
178 fn between<V>(&self, a: V, b: V) -> Expr
190 where
191 V: Into<Value>,
192 {
193 Expr::col(self.as_column_ref()).between(a, b)
194 }
195
196 fn not_between<V>(&self, a: V, b: V) -> Expr
208 where
209 V: Into<Value>,
210 {
211 Expr::col(self.as_column_ref()).not_between(a, b)
212 }
213
214 fn like<T>(&self, s: T) -> Expr
226 where
227 T: IntoLikeExpr,
228 {
229 Expr::col(self.as_column_ref()).like(s)
230 }
231
232 fn not_like<T>(&self, s: T) -> Expr
244 where
245 T: IntoLikeExpr,
246 {
247 Expr::col(self.as_column_ref()).not_like(s)
248 }
249
250 fn ilike<T>(&self, s: T) -> Expr
263 where
264 T: IntoLikeExpr,
265 {
266 use sea_query::extension::postgres::PgExpr;
267
268 Expr::col(self.as_column_ref()).ilike(s)
269 }
270
271 fn not_ilike<T>(&self, s: T) -> Expr
284 where
285 T: IntoLikeExpr,
286 {
287 use sea_query::extension::postgres::PgExpr;
288
289 Expr::col(self.as_column_ref()).not_ilike(s)
290 }
291
292 fn starts_with<T>(&self, s: T) -> Expr
309 where
310 T: Into<String>,
311 {
312 let pattern = format!("{}%", s.into());
313 Expr::col(self.as_column_ref()).like(pattern)
314 }
315
316 fn ends_with<T>(&self, s: T) -> Expr
333 where
334 T: Into<String>,
335 {
336 let pattern = format!("%{}", s.into());
337 Expr::col(self.as_column_ref()).like(pattern)
338 }
339
340 fn contains<T>(&self, s: T) -> Expr
357 where
358 T: Into<String>,
359 {
360 let pattern = format!("%{}%", s.into());
361 Expr::col(self.as_column_ref()).like(pattern)
362 }
363
364 bind_func_no_params!(max);
365 bind_func_no_params!(min);
366 bind_func_no_params!(sum);
367 bind_func_no_params!(avg);
368 bind_func_no_params!(count);
369 bind_func_no_params!(is_null);
370 bind_func_no_params!(is_not_null);
371
372 fn if_null<V>(&self, v: V) -> Expr
374 where
375 V: Into<Value>,
376 {
377 Expr::col(self.as_column_ref()).if_null(v)
378 }
379
380 bind_vec_func!(is_in);
381 bind_vec_func!(is_not_in);
382
383 #[cfg(feature = "postgres-array")]
426 fn eq_any<V, I>(&self, v: I) -> Expr
427 where
428 V: Into<Value> + sea_query::postgres_array::NotU8,
429 I: IntoIterator<Item = V>,
430 {
431 use sea_query::extension::postgres::PgFunc;
432
433 let values: Vec<Value> = v.into_iter().map(|v| v.into()).collect();
434
435 if let Some(first) = values.first() {
436 Expr::col(self.as_column_ref()).eq(PgFunc::any(Value::Array(
437 first.array_type(),
438 Some(Box::new(values)),
439 )))
440 } else {
441 Expr::col(self.as_column_ref()).is_in(std::iter::empty::<V>())
442 }
443 }
444
445 #[cfg(feature = "postgres-array")]
465 fn ne_all<V, I>(&self, v: I) -> Expr
466 where
467 V: Into<Value> + sea_query::postgres_array::NotU8,
468 I: IntoIterator<Item = V>,
469 {
470 use sea_query::extension::postgres::PgFunc;
471
472 let values: Vec<Value> = v.into_iter().map(|v| v.into()).collect();
473
474 if let Some(first) = values.first() {
475 Expr::col(self.as_column_ref()).ne(PgFunc::all(Value::Array(
476 first.array_type(),
477 Some(Box::new(values)),
478 )))
479 } else {
480 Expr::col(self.as_column_ref()).is_not_in(std::iter::empty::<V>())
481 }
482 }
483
484 bind_subquery_func!(in_subquery);
485 bind_subquery_func!(not_in_subquery);
486
487 bind_array_oper!(array_contains, Contains);
488 bind_array_oper!(array_contained, Contained);
489 bind_array_oper!(array_overlap, Overlap);
490
491 fn into_expr(self) -> Expr {
493 self.into_simple_expr()
494 }
495
496 #[allow(clippy::match_single_binding)]
498 fn into_returning_expr(self, db_backend: DbBackend) -> Expr {
499 match db_backend {
500 _ => Expr::col(self),
501 }
502 }
503
504 fn select_as(&self, expr: Expr) -> Expr {
507 self.select_enum_as(expr)
508 }
509
510 fn select_enum_as(&self, expr: Expr) -> Expr {
512 cast_enum_as(expr, &self.def(), select_enum_as)
513 }
514
515 fn save_as(&self, val: Expr) -> Expr {
518 self.save_enum_as(val)
519 }
520
521 fn save_enum_as(&self, val: Expr) -> Expr {
523 cast_enum_as(val, &self.def(), save_enum_as)
524 }
525
526 #[cfg(feature = "with-json")]
528 fn json_key(&self) -> &'static str {
529 self.as_str()
530 }
531}
532
533pub trait ColumnTypeTrait {
535 fn def(self) -> ColumnDef;
537
538 fn get_enum_name(&self) -> Option<&DynIden>;
540}
541
542impl ColumnTypeTrait for ColumnType {
543 fn def(self) -> ColumnDef {
544 ColumnDef {
545 col_type: self,
546 null: false,
547 unique: false,
548 indexed: false,
549 default: None,
550 comment: None,
551 unique_key: None,
552 renamed_from: None,
553 extra: None,
554 seaography: Default::default(),
555 }
556 }
557
558 fn get_enum_name(&self) -> Option<&DynIden> {
559 enum_name(self)
560 }
561}
562
563impl ColumnTypeTrait for ColumnDef {
564 fn def(self) -> ColumnDef {
565 self
566 }
567
568 fn get_enum_name(&self) -> Option<&DynIden> {
569 enum_name(&self.col_type)
570 }
571}
572
573fn enum_name(col_type: &ColumnType) -> Option<&DynIden> {
574 match col_type {
575 ColumnType::Enum { name, .. } => Some(name),
576 ColumnType::Array(col_type) => enum_name(col_type),
577 _ => None,
578 }
579}
580
581struct Text;
582struct TextArray;
583
584impl Iden for Text {
585 fn quoted(&self) -> Cow<'static, str> {
586 Cow::Borrowed("text")
587 }
588
589 fn unquoted(&self) -> &str {
590 match self.quoted() {
591 Cow::Borrowed(s) => s,
592 _ => unreachable!(),
593 }
594 }
595}
596
597impl Iden for TextArray {
598 fn quoted(&self) -> Cow<'static, str> {
599 Cow::Borrowed("text[]")
601 }
602
603 fn unquoted(&self) -> &str {
604 match self.quoted() {
605 Cow::Borrowed(s) => s,
606 _ => unreachable!(),
607 }
608 }
609}
610
611pub(crate) fn select_enum_as(col: Expr, _: DynIden, col_type: &ColumnType) -> Expr {
612 let type_name = match col_type {
613 ColumnType::Array(_) => TextArray.into_iden(),
614 _ => Text.into_iden(),
615 };
616 col.as_enum(type_name)
617}
618
619pub(crate) fn save_enum_as(col: Expr, enum_name: DynIden, col_type: &ColumnType) -> Expr {
620 let type_name = match col_type {
621 ColumnType::Array(_) => format!("{enum_name}[]").into_iden(),
622 _ => enum_name,
623 };
624 col.as_enum(type_name)
625}
626
627pub(crate) fn cast_enum_as<F>(expr: Expr, col_def: &ColumnDef, f: F) -> Expr
628where
629 F: Fn(Expr, DynIden, &ColumnType) -> Expr,
630{
631 let col_type = col_def.get_column_type();
632
633 match col_type {
634 #[cfg(all(feature = "with-json", feature = "postgres-array"))]
635 ColumnType::Json | ColumnType::JsonBinary => {
636 use sea_query::ArrayType;
637 use serde_json::Value as Json;
638
639 match expr {
640 Expr::Value(Value::Array(ArrayType::Json, Some(json_vec))) => {
641 let json_vec: Vec<Json> = json_vec
643 .into_iter()
644 .filter_map(|val| match val {
645 Value::Json(Some(json)) => Some(*json),
646 _ => None,
647 })
648 .collect();
649 Expr::Value(Value::Json(Some(Box::new(json_vec.into()))))
650 }
651 Expr::Value(Value::Array(ArrayType::Json, None)) => Expr::Value(Value::Json(None)),
652 _ => expr,
653 }
654 }
655 _ => match col_type.get_enum_name() {
656 Some(enum_name) => f(expr, enum_name.clone(), col_type),
657 None => expr,
658 },
659 }
660}
661
662#[cfg(test)]
663mod tests {
664 use crate::{
665 ColumnTrait, Condition, DbBackend, EntityTrait, QueryFilter, QueryTrait, tests_cfg::*,
666 };
667 use sea_query::Query;
668
669 #[test]
670 fn test_in_subquery_1() {
671 assert_eq!(
672 cake::Entity::find()
673 .filter(
674 Condition::any().add(
675 cake::Column::Id.in_subquery(
676 Query::select()
677 .expr(cake::Column::Id.max())
678 .from(cake::Entity)
679 .to_owned()
680 )
681 )
682 )
683 .build(DbBackend::MySql)
684 .to_string(),
685 [
686 "SELECT `cake`.`id`, `cake`.`name` FROM `cake`",
687 "WHERE `cake`.`id` IN (SELECT MAX(`cake`.`id`) FROM `cake`)",
688 ]
689 .join(" ")
690 );
691 }
692
693 #[test]
694 fn test_in_subquery_2() {
695 assert_eq!(
696 cake::Entity::find()
697 .filter(
698 Condition::any().add(
699 cake::Column::Id.in_subquery(
700 Query::select()
701 .column(cake_filling::Column::CakeId)
702 .from(cake_filling::Entity)
703 .to_owned()
704 )
705 )
706 )
707 .build(DbBackend::MySql)
708 .to_string(),
709 [
710 "SELECT `cake`.`id`, `cake`.`name` FROM `cake`",
711 "WHERE `cake`.`id` IN (SELECT `cake_id` FROM `cake_filling`)",
712 ]
713 .join(" ")
714 );
715 }
716
717 #[test]
718 #[cfg(feature = "macros")]
719 fn select_as_1() {
720 use crate::{ActiveModelTrait, ActiveValue, Update};
721
722 mod hello_expanded {
723 use crate as sea_orm;
724 use crate::entity::prelude::*;
725 use crate::sea_query::{Expr, ExprTrait};
726
727 #[derive(Copy, Clone, Default, Debug, DeriveEntity)]
728 pub struct Entity;
729
730 impl EntityName for Entity {
731 fn table_name(&self) -> &'static str {
732 "hello"
733 }
734 }
735
736 #[derive(Clone, Debug, PartialEq, Eq, DeriveModel, DeriveActiveModel)]
737 pub struct Model {
738 pub id: i32,
739 #[sea_orm(enum_name = "One1")]
740 pub one: i32,
741 pub two: i32,
742 #[sea_orm(enum_name = "Three3")]
743 pub three: i32,
744 }
745
746 #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
747 pub enum Column {
748 Id,
749 One1,
750 Two,
751 Three3,
752 }
753
754 impl ColumnTrait for Column {
755 type EntityName = Entity;
756
757 fn def(&self) -> ColumnDef {
758 match self {
759 Column::Id => ColumnType::Integer.def(),
760 Column::One1 => ColumnType::Integer.def(),
761 Column::Two => ColumnType::Integer.def(),
762 Column::Three3 => ColumnType::Integer.def(),
763 }
764 }
765
766 fn select_as(&self, expr: Expr) -> Expr {
767 match self {
768 Self::Two => expr.cast_as("integer"),
769 _ => self.select_enum_as(expr),
770 }
771 }
772 }
773
774 #[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
775 pub enum PrimaryKey {
776 Id,
777 }
778
779 impl PrimaryKeyTrait for PrimaryKey {
780 type ValueType = i32;
781
782 fn auto_increment() -> bool {
783 true
784 }
785 }
786
787 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
788 pub enum Relation {}
789
790 impl ActiveModelBehavior for ActiveModel {}
791 }
792
793 #[allow(clippy::enum_variant_names)]
794 mod hello_compact {
795 use crate as sea_orm;
796 use crate::entity::prelude::*;
797
798 #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
799 #[sea_orm(table_name = "hello")]
800 pub struct Model {
801 #[sea_orm(primary_key)]
802 pub id: i32,
803 #[sea_orm(enum_name = "One1")]
804 pub one: i32,
805 #[sea_orm(select_as = "integer")]
806 pub two: i32,
807 #[sea_orm(enum_name = "Three3")]
808 pub three: i32,
809 }
810
811 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
812 pub enum Relation {}
813
814 impl ActiveModelBehavior for ActiveModel {}
815 }
816
817 fn assert_it<E, A>(active_model: A)
818 where
819 E: EntityTrait,
820 A: ActiveModelTrait<Entity = E>,
821 {
822 assert_eq!(
823 E::find().build(DbBackend::Postgres).to_string(),
824 r#"SELECT "hello"."id", "hello"."one1", CAST("hello"."two" AS integer), "hello"."three3" FROM "hello""#,
825 );
826 assert_eq!(
827 Update::one(active_model)
828 .validate()
829 .unwrap()
830 .build(DbBackend::Postgres)
831 .to_string(),
832 r#"UPDATE "hello" SET "one1" = 1, "two" = 2, "three3" = 3 WHERE "hello"."id" = 1"#,
833 );
834 }
835
836 assert_it(hello_expanded::ActiveModel {
837 id: ActiveValue::set(1),
838 one: ActiveValue::set(1),
839 two: ActiveValue::set(2),
840 three: ActiveValue::set(3),
841 });
842 assert_it(hello_compact::ActiveModel {
843 id: ActiveValue::set(1),
844 one: ActiveValue::set(1),
845 two: ActiveValue::set(2),
846 three: ActiveValue::set(3),
847 });
848 }
849
850 #[test]
851 #[cfg(feature = "macros")]
852 fn save_as_1() {
853 use crate::{ActiveModelTrait, ActiveValue, Update};
854
855 mod hello_expanded {
856 use crate as sea_orm;
857 use crate::entity::prelude::*;
858 use crate::sea_query::{Expr, ExprTrait};
859
860 #[derive(Copy, Clone, Default, Debug, DeriveEntity)]
861 pub struct Entity;
862
863 impl EntityName for Entity {
864 fn table_name(&self) -> &'static str {
865 "hello"
866 }
867 }
868
869 #[derive(Clone, Debug, PartialEq, Eq, DeriveModel, DeriveActiveModel)]
870 pub struct Model {
871 pub id: i32,
872 #[sea_orm(enum_name = "One1")]
873 pub one: i32,
874 pub two: i32,
875 #[sea_orm(enum_name = "Three3")]
876 pub three: i32,
877 }
878
879 #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
880 pub enum Column {
881 Id,
882 One1,
883 Two,
884 Three3,
885 }
886
887 impl ColumnTrait for Column {
888 type EntityName = Entity;
889
890 fn def(&self) -> ColumnDef {
891 match self {
892 Column::Id => ColumnType::Integer.def(),
893 Column::One1 => ColumnType::Integer.def(),
894 Column::Two => ColumnType::Integer.def(),
895 Column::Three3 => ColumnType::Integer.def(),
896 }
897 }
898
899 fn save_as(&self, val: Expr) -> Expr {
900 match self {
901 Self::Two => val.cast_as("text"),
902 _ => self.save_enum_as(val),
903 }
904 }
905 }
906
907 #[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
908 pub enum PrimaryKey {
909 Id,
910 }
911
912 impl PrimaryKeyTrait for PrimaryKey {
913 type ValueType = i32;
914
915 fn auto_increment() -> bool {
916 true
917 }
918 }
919
920 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
921 pub enum Relation {}
922
923 impl ActiveModelBehavior for ActiveModel {}
924 }
925
926 #[allow(clippy::enum_variant_names)]
927 mod hello_compact {
928 use crate as sea_orm;
929 use crate::entity::prelude::*;
930
931 #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
932 #[sea_orm(table_name = "hello")]
933 pub struct Model {
934 #[sea_orm(primary_key)]
935 pub id: i32,
936 #[sea_orm(enum_name = "One1")]
937 pub one: i32,
938 #[sea_orm(save_as = "text")]
939 pub two: i32,
940 #[sea_orm(enum_name = "Three3")]
941 pub three: i32,
942 }
943
944 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
945 pub enum Relation {}
946
947 impl ActiveModelBehavior for ActiveModel {}
948 }
949
950 fn assert_it<E, A>(active_model: A)
951 where
952 E: EntityTrait,
953 A: ActiveModelTrait<Entity = E>,
954 {
955 assert_eq!(
956 E::find().build(DbBackend::Postgres).to_string(),
957 r#"SELECT "hello"."id", "hello"."one1", "hello"."two", "hello"."three3" FROM "hello""#,
958 );
959 assert_eq!(
960 Update::one(active_model)
961 .validate()
962 .unwrap()
963 .build(DbBackend::Postgres)
964 .to_string(),
965 r#"UPDATE "hello" SET "one1" = 1, "two" = CAST(2 AS text), "three3" = 3 WHERE "hello"."id" = 1"#,
966 );
967 }
968
969 assert_it(hello_expanded::ActiveModel {
970 id: ActiveValue::set(1),
971 one: ActiveValue::set(1),
972 two: ActiveValue::set(2),
973 three: ActiveValue::set(3),
974 });
975 assert_it(hello_compact::ActiveModel {
976 id: ActiveValue::set(1),
977 one: ActiveValue::set(1),
978 two: ActiveValue::set(2),
979 three: ActiveValue::set(3),
980 });
981 }
982
983 #[test]
984 #[cfg(feature = "macros")]
985 fn select_as_and_value_1() {
986 use crate::{ActiveModelTrait, ActiveValue, Update};
987
988 mod hello_expanded {
989 use crate as sea_orm;
990 use crate::entity::prelude::*;
991 use crate::sea_query::{Expr, ExprTrait};
992
993 #[derive(Copy, Clone, Default, Debug, DeriveEntity)]
994 pub struct Entity;
995
996 impl EntityName for Entity {
997 fn table_name(&self) -> &'static str {
998 "hello"
999 }
1000 }
1001
1002 #[derive(Clone, Debug, PartialEq, Eq, DeriveModel, DeriveActiveModel)]
1003 pub struct Model {
1004 pub id: i32,
1005 #[sea_orm(enum_name = "One1")]
1006 pub one: i32,
1007 pub two: i32,
1008 #[sea_orm(enum_name = "Three3")]
1009 pub three: i32,
1010 }
1011
1012 #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
1013 pub enum Column {
1014 Id,
1015 One1,
1016 Two,
1017 Three3,
1018 }
1019
1020 impl ColumnTrait for Column {
1021 type EntityName = Entity;
1022
1023 fn def(&self) -> ColumnDef {
1024 match self {
1025 Column::Id => ColumnType::Integer.def(),
1026 Column::One1 => ColumnType::Integer.def(),
1027 Column::Two => ColumnType::Integer.def(),
1028 Column::Three3 => ColumnType::Integer.def(),
1029 }
1030 }
1031
1032 fn select_as(&self, expr: Expr) -> Expr {
1033 match self {
1034 Self::Two => expr.cast_as("integer"),
1035 _ => self.select_enum_as(expr),
1036 }
1037 }
1038
1039 fn save_as(&self, val: Expr) -> Expr {
1040 match self {
1041 Self::Two => val.cast_as("text"),
1042 _ => self.save_enum_as(val),
1043 }
1044 }
1045 }
1046
1047 #[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
1048 pub enum PrimaryKey {
1049 Id,
1050 }
1051
1052 impl PrimaryKeyTrait for PrimaryKey {
1053 type ValueType = i32;
1054
1055 fn auto_increment() -> bool {
1056 true
1057 }
1058 }
1059
1060 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1061 pub enum Relation {}
1062
1063 impl ActiveModelBehavior for ActiveModel {}
1064 }
1065
1066 #[allow(clippy::enum_variant_names)]
1067 mod hello_compact {
1068 use crate as sea_orm;
1069 use crate::entity::prelude::*;
1070
1071 #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
1072 #[sea_orm(table_name = "hello")]
1073 pub struct Model {
1074 #[sea_orm(primary_key)]
1075 pub id: i32,
1076 #[sea_orm(enum_name = "One1")]
1077 pub one: i32,
1078 #[sea_orm(select_as = "integer", save_as = "text")]
1079 pub two: i32,
1080 #[sea_orm(enum_name = "Three3")]
1081 pub three: i32,
1082 }
1083
1084 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1085 pub enum Relation {}
1086
1087 impl ActiveModelBehavior for ActiveModel {}
1088 }
1089
1090 fn assert_it<E, A>(active_model: A)
1091 where
1092 E: EntityTrait,
1093 A: ActiveModelTrait<Entity = E>,
1094 {
1095 assert_eq!(
1096 E::find().build(DbBackend::Postgres).to_string(),
1097 r#"SELECT "hello"."id", "hello"."one1", CAST("hello"."two" AS integer), "hello"."three3" FROM "hello""#,
1098 );
1099 assert_eq!(
1100 Update::one(active_model)
1101 .validate()
1102 .unwrap()
1103 .build(DbBackend::Postgres)
1104 .to_string(),
1105 r#"UPDATE "hello" SET "one1" = 1, "two" = CAST(2 AS text), "three3" = 3 WHERE "hello"."id" = 1"#,
1106 );
1107 }
1108
1109 assert_it(hello_expanded::ActiveModel {
1110 id: ActiveValue::set(1),
1111 one: ActiveValue::set(1),
1112 two: ActiveValue::set(2),
1113 three: ActiveValue::set(3),
1114 });
1115 assert_it(hello_compact::ActiveModel {
1116 id: ActiveValue::set(1),
1117 one: ActiveValue::set(1),
1118 two: ActiveValue::set(2),
1119 three: ActiveValue::set(3),
1120 });
1121 }
1122}