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::with_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")]
396 fn eq_any<V, I>(&self, v: I) -> Expr
397 where
398 V: Into<Value> + sea_query::ValueType + sea_query::with_array::NotU8,
399 I: IntoIterator<Item = V>,
400 {
401 use sea_query::extension::postgres::PgFunc;
402
403 let vec: Vec<_> = v.into_iter().collect();
404 Expr::col(self.as_column_ref()).eq(PgFunc::any(vec))
405 }
406
407 bind_subquery_func!(in_subquery);
408 bind_subquery_func!(not_in_subquery);
409
410 bind_array_oper!(array_contains, Contains);
411 bind_array_oper!(array_contained, Contained);
412 bind_array_oper!(array_overlap, Overlap);
413
414 fn into_expr(self) -> Expr {
416 self.into_simple_expr()
417 }
418
419 #[allow(clippy::match_single_binding)]
421 fn into_returning_expr(self, db_backend: DbBackend) -> Expr {
422 match db_backend {
423 _ => Expr::col(self),
424 }
425 }
426
427 fn select_as(&self, expr: Expr) -> Expr {
430 self.select_enum_as(expr)
431 }
432
433 fn select_enum_as(&self, expr: Expr) -> Expr {
435 cast_enum_as(expr, &self.def(), select_enum_as)
436 }
437
438 fn save_as(&self, val: Expr) -> Expr {
441 self.save_enum_as(val)
442 }
443
444 fn save_enum_as(&self, val: Expr) -> Expr {
446 cast_enum_as(val, &self.def(), save_enum_as)
447 }
448
449 #[cfg(feature = "with-json")]
451 fn json_key(&self) -> &'static str {
452 self.as_str()
453 }
454}
455
456pub trait ColumnTypeTrait {
458 fn def(self) -> ColumnDef;
460
461 fn get_enum_name(&self) -> Option<&DynIden>;
463}
464
465impl ColumnTypeTrait for ColumnType {
466 fn def(self) -> ColumnDef {
467 ColumnDef {
468 col_type: self,
469 null: false,
470 unique: false,
471 indexed: false,
472 default: None,
473 comment: None,
474 unique_key: None,
475 renamed_from: None,
476 extra: None,
477 seaography: Default::default(),
478 }
479 }
480
481 fn get_enum_name(&self) -> Option<&DynIden> {
482 enum_name(self)
483 }
484}
485
486impl ColumnTypeTrait for ColumnDef {
487 fn def(self) -> ColumnDef {
488 self
489 }
490
491 fn get_enum_name(&self) -> Option<&DynIden> {
492 enum_name(&self.col_type)
493 }
494}
495
496fn enum_name(col_type: &ColumnType) -> Option<&DynIden> {
497 match col_type {
498 ColumnType::Enum { name, .. } => Some(name),
499 ColumnType::Array(col_type) => enum_name(col_type),
500 _ => None,
501 }
502}
503
504struct Text;
505struct TextArray;
506
507impl Iden for Text {
508 fn quoted(&self) -> Cow<'static, str> {
509 Cow::Borrowed("text")
510 }
511
512 fn unquoted(&self) -> &str {
513 match self.quoted() {
514 Cow::Borrowed(s) => s,
515 _ => unreachable!(),
516 }
517 }
518}
519
520impl Iden for TextArray {
521 fn quoted(&self) -> Cow<'static, str> {
522 Cow::Borrowed("text[]")
524 }
525
526 fn unquoted(&self) -> &str {
527 match self.quoted() {
528 Cow::Borrowed(s) => s,
529 _ => unreachable!(),
530 }
531 }
532}
533
534pub(crate) fn select_enum_as(col: Expr, _: DynIden, col_type: &ColumnType) -> Expr {
535 let type_name = match col_type {
536 ColumnType::Array(_) => TextArray.into_iden(),
537 _ => Text.into_iden(),
538 };
539 col.as_enum(type_name)
540}
541
542pub(crate) fn save_enum_as(col: Expr, enum_name: DynIden, col_type: &ColumnType) -> Expr {
543 let type_name = match col_type {
544 ColumnType::Array(_) => format!("{enum_name}[]").into_iden(),
545 _ => enum_name,
546 };
547 col.as_enum(type_name)
548}
549
550pub(crate) fn cast_enum_as<F>(expr: Expr, col_def: &ColumnDef, f: F) -> Expr
551where
552 F: Fn(Expr, DynIden, &ColumnType) -> Expr,
553{
554 let col_type = col_def.get_column_type();
555
556 match col_type {
557 #[cfg(all(feature = "with-json", feature = "postgres-array"))]
558 ColumnType::Json | ColumnType::JsonBinary => {
559 use sea_query::ArrayType;
560 use serde_json::Value as Json;
561
562 match expr {
563 Expr::Value(Value::Array(ArrayType::Json, Some(json_vec))) => {
564 let json_vec: Vec<Json> = json_vec
566 .into_iter()
567 .filter_map(|val| match val {
568 Value::Json(Some(json)) => Some(*json),
569 _ => None,
570 })
571 .collect();
572 Expr::Value(Value::Json(Some(Box::new(json_vec.into()))))
573 }
574 Expr::Value(Value::Array(ArrayType::Json, None)) => Expr::Value(Value::Json(None)),
575 _ => expr,
576 }
577 }
578 _ => match col_type.get_enum_name() {
579 Some(enum_name) => f(expr, enum_name.clone(), col_type),
580 None => expr,
581 },
582 }
583}
584
585#[cfg(test)]
586mod tests {
587 use crate::{
588 ColumnTrait, Condition, DbBackend, EntityTrait, QueryFilter, QueryTrait, tests_cfg::*,
589 };
590 use sea_query::Query;
591
592 #[test]
593 fn test_in_subquery_1() {
594 assert_eq!(
595 cake::Entity::find()
596 .filter(
597 Condition::any().add(
598 cake::Column::Id.in_subquery(
599 Query::select()
600 .expr(cake::Column::Id.max())
601 .from(cake::Entity)
602 .to_owned()
603 )
604 )
605 )
606 .build(DbBackend::MySql)
607 .to_string(),
608 [
609 "SELECT `cake`.`id`, `cake`.`name` FROM `cake`",
610 "WHERE `cake`.`id` IN (SELECT MAX(`cake`.`id`) FROM `cake`)",
611 ]
612 .join(" ")
613 );
614 }
615
616 #[test]
617 fn test_in_subquery_2() {
618 assert_eq!(
619 cake::Entity::find()
620 .filter(
621 Condition::any().add(
622 cake::Column::Id.in_subquery(
623 Query::select()
624 .column(cake_filling::Column::CakeId)
625 .from(cake_filling::Entity)
626 .to_owned()
627 )
628 )
629 )
630 .build(DbBackend::MySql)
631 .to_string(),
632 [
633 "SELECT `cake`.`id`, `cake`.`name` FROM `cake`",
634 "WHERE `cake`.`id` IN (SELECT `cake_id` FROM `cake_filling`)",
635 ]
636 .join(" ")
637 );
638 }
639
640 #[test]
641 #[cfg(feature = "macros")]
642 fn select_as_1() {
643 use crate::{ActiveModelTrait, ActiveValue, Update};
644
645 mod hello_expanded {
646 use crate as sea_orm;
647 use crate::entity::prelude::*;
648 use crate::sea_query::{Expr, ExprTrait};
649
650 #[derive(Copy, Clone, Default, Debug, DeriveEntity)]
651 pub struct Entity;
652
653 impl EntityName for Entity {
654 fn table_name(&self) -> &'static str {
655 "hello"
656 }
657 }
658
659 #[derive(Clone, Debug, PartialEq, Eq, DeriveModel, DeriveActiveModel)]
660 pub struct Model {
661 pub id: i32,
662 #[sea_orm(enum_name = "One1")]
663 pub one: i32,
664 pub two: i32,
665 #[sea_orm(enum_name = "Three3")]
666 pub three: i32,
667 }
668
669 #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
670 pub enum Column {
671 Id,
672 One1,
673 Two,
674 Three3,
675 }
676
677 impl ColumnTrait for Column {
678 type EntityName = Entity;
679
680 fn def(&self) -> ColumnDef {
681 match self {
682 Column::Id => ColumnType::Integer.def(),
683 Column::One1 => ColumnType::Integer.def(),
684 Column::Two => ColumnType::Integer.def(),
685 Column::Three3 => ColumnType::Integer.def(),
686 }
687 }
688
689 fn select_as(&self, expr: Expr) -> Expr {
690 match self {
691 Self::Two => expr.cast_as("integer"),
692 _ => self.select_enum_as(expr),
693 }
694 }
695 }
696
697 #[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
698 pub enum PrimaryKey {
699 Id,
700 }
701
702 impl PrimaryKeyTrait for PrimaryKey {
703 type ValueType = i32;
704
705 fn auto_increment() -> bool {
706 true
707 }
708 }
709
710 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
711 pub enum Relation {}
712
713 impl ActiveModelBehavior for ActiveModel {}
714 }
715
716 #[allow(clippy::enum_variant_names)]
717 mod hello_compact {
718 use crate as sea_orm;
719 use crate::entity::prelude::*;
720
721 #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
722 #[sea_orm(table_name = "hello")]
723 pub struct Model {
724 #[sea_orm(primary_key)]
725 pub id: i32,
726 #[sea_orm(enum_name = "One1")]
727 pub one: i32,
728 #[sea_orm(select_as = "integer")]
729 pub two: i32,
730 #[sea_orm(enum_name = "Three3")]
731 pub three: i32,
732 }
733
734 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
735 pub enum Relation {}
736
737 impl ActiveModelBehavior for ActiveModel {}
738 }
739
740 fn assert_it<E, A>(active_model: A)
741 where
742 E: EntityTrait,
743 A: ActiveModelTrait<Entity = E>,
744 {
745 assert_eq!(
746 E::find().build(DbBackend::Postgres).to_string(),
747 r#"SELECT "hello"."id", "hello"."one1", CAST("hello"."two" AS integer), "hello"."three3" FROM "hello""#,
748 );
749 assert_eq!(
750 Update::one(active_model)
751 .validate()
752 .unwrap()
753 .build(DbBackend::Postgres)
754 .to_string(),
755 r#"UPDATE "hello" SET "one1" = 1, "two" = 2, "three3" = 3 WHERE "hello"."id" = 1"#,
756 );
757 }
758
759 assert_it(hello_expanded::ActiveModel {
760 id: ActiveValue::set(1),
761 one: ActiveValue::set(1),
762 two: ActiveValue::set(2),
763 three: ActiveValue::set(3),
764 });
765 assert_it(hello_compact::ActiveModel {
766 id: ActiveValue::set(1),
767 one: ActiveValue::set(1),
768 two: ActiveValue::set(2),
769 three: ActiveValue::set(3),
770 });
771 }
772
773 #[test]
774 #[cfg(feature = "macros")]
775 fn save_as_1() {
776 use crate::{ActiveModelTrait, ActiveValue, Update};
777
778 mod hello_expanded {
779 use crate as sea_orm;
780 use crate::entity::prelude::*;
781 use crate::sea_query::{Expr, ExprTrait};
782
783 #[derive(Copy, Clone, Default, Debug, DeriveEntity)]
784 pub struct Entity;
785
786 impl EntityName for Entity {
787 fn table_name(&self) -> &'static str {
788 "hello"
789 }
790 }
791
792 #[derive(Clone, Debug, PartialEq, Eq, DeriveModel, DeriveActiveModel)]
793 pub struct Model {
794 pub id: i32,
795 #[sea_orm(enum_name = "One1")]
796 pub one: i32,
797 pub two: i32,
798 #[sea_orm(enum_name = "Three3")]
799 pub three: i32,
800 }
801
802 #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
803 pub enum Column {
804 Id,
805 One1,
806 Two,
807 Three3,
808 }
809
810 impl ColumnTrait for Column {
811 type EntityName = Entity;
812
813 fn def(&self) -> ColumnDef {
814 match self {
815 Column::Id => ColumnType::Integer.def(),
816 Column::One1 => ColumnType::Integer.def(),
817 Column::Two => ColumnType::Integer.def(),
818 Column::Three3 => ColumnType::Integer.def(),
819 }
820 }
821
822 fn save_as(&self, val: Expr) -> Expr {
823 match self {
824 Self::Two => val.cast_as("text"),
825 _ => self.save_enum_as(val),
826 }
827 }
828 }
829
830 #[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
831 pub enum PrimaryKey {
832 Id,
833 }
834
835 impl PrimaryKeyTrait for PrimaryKey {
836 type ValueType = i32;
837
838 fn auto_increment() -> bool {
839 true
840 }
841 }
842
843 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
844 pub enum Relation {}
845
846 impl ActiveModelBehavior for ActiveModel {}
847 }
848
849 #[allow(clippy::enum_variant_names)]
850 mod hello_compact {
851 use crate as sea_orm;
852 use crate::entity::prelude::*;
853
854 #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
855 #[sea_orm(table_name = "hello")]
856 pub struct Model {
857 #[sea_orm(primary_key)]
858 pub id: i32,
859 #[sea_orm(enum_name = "One1")]
860 pub one: i32,
861 #[sea_orm(save_as = "text")]
862 pub two: i32,
863 #[sea_orm(enum_name = "Three3")]
864 pub three: i32,
865 }
866
867 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
868 pub enum Relation {}
869
870 impl ActiveModelBehavior for ActiveModel {}
871 }
872
873 fn assert_it<E, A>(active_model: A)
874 where
875 E: EntityTrait,
876 A: ActiveModelTrait<Entity = E>,
877 {
878 assert_eq!(
879 E::find().build(DbBackend::Postgres).to_string(),
880 r#"SELECT "hello"."id", "hello"."one1", "hello"."two", "hello"."three3" FROM "hello""#,
881 );
882 assert_eq!(
883 Update::one(active_model)
884 .validate()
885 .unwrap()
886 .build(DbBackend::Postgres)
887 .to_string(),
888 r#"UPDATE "hello" SET "one1" = 1, "two" = CAST(2 AS text), "three3" = 3 WHERE "hello"."id" = 1"#,
889 );
890 }
891
892 assert_it(hello_expanded::ActiveModel {
893 id: ActiveValue::set(1),
894 one: ActiveValue::set(1),
895 two: ActiveValue::set(2),
896 three: ActiveValue::set(3),
897 });
898 assert_it(hello_compact::ActiveModel {
899 id: ActiveValue::set(1),
900 one: ActiveValue::set(1),
901 two: ActiveValue::set(2),
902 three: ActiveValue::set(3),
903 });
904 }
905
906 #[test]
907 #[cfg(feature = "macros")]
908 fn select_as_and_value_1() {
909 use crate::{ActiveModelTrait, ActiveValue, Update};
910
911 mod hello_expanded {
912 use crate as sea_orm;
913 use crate::entity::prelude::*;
914 use crate::sea_query::{Expr, ExprTrait};
915
916 #[derive(Copy, Clone, Default, Debug, DeriveEntity)]
917 pub struct Entity;
918
919 impl EntityName for Entity {
920 fn table_name(&self) -> &'static str {
921 "hello"
922 }
923 }
924
925 #[derive(Clone, Debug, PartialEq, Eq, DeriveModel, DeriveActiveModel)]
926 pub struct Model {
927 pub id: i32,
928 #[sea_orm(enum_name = "One1")]
929 pub one: i32,
930 pub two: i32,
931 #[sea_orm(enum_name = "Three3")]
932 pub three: i32,
933 }
934
935 #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
936 pub enum Column {
937 Id,
938 One1,
939 Two,
940 Three3,
941 }
942
943 impl ColumnTrait for Column {
944 type EntityName = Entity;
945
946 fn def(&self) -> ColumnDef {
947 match self {
948 Column::Id => ColumnType::Integer.def(),
949 Column::One1 => ColumnType::Integer.def(),
950 Column::Two => ColumnType::Integer.def(),
951 Column::Three3 => ColumnType::Integer.def(),
952 }
953 }
954
955 fn select_as(&self, expr: Expr) -> Expr {
956 match self {
957 Self::Two => expr.cast_as("integer"),
958 _ => self.select_enum_as(expr),
959 }
960 }
961
962 fn save_as(&self, val: Expr) -> Expr {
963 match self {
964 Self::Two => val.cast_as("text"),
965 _ => self.save_enum_as(val),
966 }
967 }
968 }
969
970 #[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
971 pub enum PrimaryKey {
972 Id,
973 }
974
975 impl PrimaryKeyTrait for PrimaryKey {
976 type ValueType = i32;
977
978 fn auto_increment() -> bool {
979 true
980 }
981 }
982
983 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
984 pub enum Relation {}
985
986 impl ActiveModelBehavior for ActiveModel {}
987 }
988
989 #[allow(clippy::enum_variant_names)]
990 mod hello_compact {
991 use crate as sea_orm;
992 use crate::entity::prelude::*;
993
994 #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
995 #[sea_orm(table_name = "hello")]
996 pub struct Model {
997 #[sea_orm(primary_key)]
998 pub id: i32,
999 #[sea_orm(enum_name = "One1")]
1000 pub one: i32,
1001 #[sea_orm(select_as = "integer", save_as = "text")]
1002 pub two: i32,
1003 #[sea_orm(enum_name = "Three3")]
1004 pub three: i32,
1005 }
1006
1007 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1008 pub enum Relation {}
1009
1010 impl ActiveModelBehavior for ActiveModel {}
1011 }
1012
1013 fn assert_it<E, A>(active_model: A)
1014 where
1015 E: EntityTrait,
1016 A: ActiveModelTrait<Entity = E>,
1017 {
1018 assert_eq!(
1019 E::find().build(DbBackend::Postgres).to_string(),
1020 r#"SELECT "hello"."id", "hello"."one1", CAST("hello"."two" AS integer), "hello"."three3" FROM "hello""#,
1021 );
1022 assert_eq!(
1023 Update::one(active_model)
1024 .validate()
1025 .unwrap()
1026 .build(DbBackend::Postgres)
1027 .to_string(),
1028 r#"UPDATE "hello" SET "one1" = 1, "two" = CAST(2 AS text), "three3" = 3 WHERE "hello"."id" = 1"#,
1029 );
1030 }
1031
1032 assert_it(hello_expanded::ActiveModel {
1033 id: ActiveValue::set(1),
1034 one: ActiveValue::set(1),
1035 two: ActiveValue::set(2),
1036 three: ActiveValue::set(3),
1037 });
1038 assert_it(hello_compact::ActiveModel {
1039 id: ActiveValue::set(1),
1040 one: ActiveValue::set(1),
1041 two: ActiveValue::set(2),
1042 three: ActiveValue::set(3),
1043 });
1044 }
1045}