1use crate::{
2 ColumnDef, ColumnType, DbBackend, EntityName, Iden, IdenStatic, IntoSimpleExpr, Iterable,
3};
4#[cfg(feature = "postgres-array")]
5use sea_query::ArrayElement;
6use sea_query::{
7 BinOper, DynIden, Expr, ExprTrait, IntoIden, IntoLikeExpr, SeaRc, SelectStatement, Value,
8};
9use std::{borrow::Cow, str::FromStr};
10
11mod types;
12pub use types::*;
13
14pub(crate) mod macros {
15 macro_rules! bind_oper {
16 ($vis:vis $op:ident, $bin_op:ident) => {
17 #[allow(missing_docs)]
18 $vis fn $op<V>(&self, v: V) -> Expr
19 where
20 V: Into<Value>,
21 {
22 let expr = self.save_as(Expr::val(v));
23 Expr::col(self.as_column_ref()).binary(BinOper::$bin_op, expr)
24 }
25 };
26 }
27
28 macro_rules! bind_func_no_params {
29 ($vis:vis $func:ident) => {
30 $vis fn $func(&self) -> Expr {
32 Expr::col(self.as_column_ref()).$func()
33 }
34 };
35 }
36
37 macro_rules! bind_vec_func {
38 ($vis:vis $func:ident) => {
39 #[allow(missing_docs)]
40 #[allow(clippy::wrong_self_convention)]
41 $vis fn $func<V, I>(&self, v: I) -> Expr
42 where
43 V: Into<Value>,
44 I: IntoIterator<Item = V>,
45 {
46 let v_with_enum_cast = v.into_iter().map(|v| self.save_as(Expr::val(v)));
47 Expr::col(self.as_column_ref()).$func(v_with_enum_cast)
48 }
49 };
50 }
51
52 macro_rules! bind_subquery_func {
53 ($vis:vis $func:ident) => {
54 #[allow(clippy::wrong_self_convention)]
55 #[allow(missing_docs)]
56 $vis fn $func(&self, s: SelectStatement) -> Expr {
57 Expr::col(self.as_column_ref()).$func(s)
58 }
59 };
60 }
61
62 macro_rules! bind_array_oper {
63 ($vis:vis $op:ident, $oper:ident) => {
64 #[cfg(feature = "postgres-array")]
65 $vis fn $op<A>(&self, arr: A) -> Expr
67 where
68 A: Into<sea_query::value::Array>,
69 {
70 use sea_query::extension::postgres::PgBinOper;
71
72 let value = Value::Array(arr.into());
73 Expr::col(self.as_column_ref()).binary(PgBinOper::$oper, self.save_as(Expr::val(value)))
74 }
75 };
76 }
77
78 pub(crate) use bind_array_oper;
79 pub(crate) use bind_func_no_params;
80 pub(crate) use bind_oper;
81 pub(crate) use bind_subquery_func;
82 pub(crate) use bind_vec_func;
83}
84
85use macros::*;
86
87pub trait ColumnTrait: IdenStatic + Iterable + FromStr {
89 #[allow(missing_docs)]
90 type EntityName: EntityName;
91
92 fn def(&self) -> ColumnDef;
94
95 fn enum_type_name(&self) -> Option<&'static str> {
97 None
98 }
99
100 fn entity_name(&self) -> DynIden {
102 SeaRc::new(Self::EntityName::default())
103 }
104
105 fn as_column_ref(&self) -> (DynIden, DynIden) {
107 (self.entity_name(), SeaRc::new(*self))
108 }
109
110 fn eq<V>(&self, v: V) -> Expr
130 where
131 V: Into<Value>,
132 {
133 let v = v.into();
134 if v == v.as_null() {
135 Expr::col(self.as_column_ref()).is_null()
136 } else {
137 let expr = self.save_as(Expr::val(v));
138 Expr::col(self.as_column_ref()).eq(expr)
139 }
140 }
141
142 fn ne<V>(&self, v: V) -> Expr
162 where
163 V: Into<Value>,
164 {
165 let v = v.into();
166 if v == v.as_null() {
167 Expr::col(self.as_column_ref()).is_not_null()
168 } else {
169 let expr = self.save_as(Expr::val(v));
170 Expr::col(self.as_column_ref()).ne(expr)
171 }
172 }
173
174 bind_oper!(gt, GreaterThan);
175 bind_oper!(gte, GreaterThanOrEqual);
176 bind_oper!(lt, SmallerThan);
177 bind_oper!(lte, SmallerThanOrEqual);
178
179 fn between<V>(&self, a: V, b: V) -> Expr
191 where
192 V: Into<Value>,
193 {
194 Expr::col(self.as_column_ref()).between(a, b)
195 }
196
197 fn not_between<V>(&self, a: V, b: V) -> Expr
209 where
210 V: Into<Value>,
211 {
212 Expr::col(self.as_column_ref()).not_between(a, b)
213 }
214
215 fn like<T>(&self, s: T) -> Expr
227 where
228 T: IntoLikeExpr,
229 {
230 Expr::col(self.as_column_ref()).like(s)
231 }
232
233 fn not_like<T>(&self, s: T) -> Expr
245 where
246 T: IntoLikeExpr,
247 {
248 Expr::col(self.as_column_ref()).not_like(s)
249 }
250
251 fn ilike<T>(&self, s: T) -> Expr
264 where
265 T: IntoLikeExpr,
266 {
267 use sea_query::extension::postgres::PgExpr;
268
269 Expr::col(self.as_column_ref()).ilike(s)
270 }
271
272 fn not_ilike<T>(&self, s: T) -> Expr
285 where
286 T: IntoLikeExpr,
287 {
288 use sea_query::extension::postgres::PgExpr;
289
290 Expr::col(self.as_column_ref()).not_ilike(s)
291 }
292
293 fn starts_with<T>(&self, s: T) -> Expr
310 where
311 T: Into<String>,
312 {
313 let pattern = format!("{}%", s.into());
314 Expr::col(self.as_column_ref()).like(pattern)
315 }
316
317 fn ends_with<T>(&self, s: T) -> Expr
334 where
335 T: Into<String>,
336 {
337 let pattern = format!("%{}", s.into());
338 Expr::col(self.as_column_ref()).like(pattern)
339 }
340
341 fn contains<T>(&self, s: T) -> Expr
358 where
359 T: Into<String>,
360 {
361 let pattern = format!("%{}%", s.into());
362 Expr::col(self.as_column_ref()).like(pattern)
363 }
364
365 bind_func_no_params!(max);
366 bind_func_no_params!(min);
367 bind_func_no_params!(sum);
368 bind_func_no_params!(avg);
369 bind_func_no_params!(count);
370 bind_func_no_params!(is_null);
371 bind_func_no_params!(is_not_null);
372
373 fn if_null<V>(&self, v: V) -> Expr
375 where
376 V: Into<Value>,
377 {
378 Expr::col(self.as_column_ref()).if_null(v)
379 }
380
381 bind_vec_func!(is_in);
382 bind_vec_func!(is_not_in);
383
384 #[cfg(feature = "postgres-array")]
397 fn eq_any<T>(&self, arr: impl IntoIterator<Item = T>) -> Expr
398 where
399 T: ArrayElement,
400 {
401 use sea_query::extension::postgres::PgFunc;
402
403 let value = Value::Array(arr.into_iter().collect());
404 Expr::col(self.as_column_ref()).eq(PgFunc::any(Expr::val(value)))
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::value::{Array, ArrayType};
560 use serde_json::Value as Json;
561
562 match expr {
563 Expr::Value(Value::Array(Array::Json(json_vec))) => {
564 let json_vec: Vec<Json> = json_vec.into_vec().into_iter().flatten().collect();
566 Expr::Value(Value::Json(Some(json_vec.into())))
567 }
568 Expr::Value(Value::Array(Array::Null(ArrayType::Json))) => {
569 Expr::Value(Value::Json(None))
570 }
571 _ => expr,
572 }
573 }
574 _ => match col_type.get_enum_name() {
575 Some(enum_name) => f(expr, enum_name.clone(), col_type),
576 None => expr,
577 },
578 }
579}
580
581#[cfg(test)]
582mod tests {
583 use crate::{
584 ColumnTrait, Condition, DbBackend, EntityTrait, QueryFilter, QueryTrait, tests_cfg::*,
585 };
586 use sea_query::Query;
587
588 #[test]
589 fn test_in_subquery_1() {
590 assert_eq!(
591 cake::Entity::find()
592 .filter(
593 Condition::any().add(
594 cake::Column::Id.in_subquery(
595 Query::select()
596 .expr(cake::Column::Id.max())
597 .from(cake::Entity)
598 .to_owned()
599 )
600 )
601 )
602 .build(DbBackend::MySql)
603 .to_string(),
604 [
605 "SELECT `cake`.`id`, `cake`.`name` FROM `cake`",
606 "WHERE `cake`.`id` IN (SELECT MAX(`cake`.`id`) FROM `cake`)",
607 ]
608 .join(" ")
609 );
610 }
611
612 #[test]
613 fn test_in_subquery_2() {
614 assert_eq!(
615 cake::Entity::find()
616 .filter(
617 Condition::any().add(
618 cake::Column::Id.in_subquery(
619 Query::select()
620 .column(cake_filling::Column::CakeId)
621 .from(cake_filling::Entity)
622 .to_owned()
623 )
624 )
625 )
626 .build(DbBackend::MySql)
627 .to_string(),
628 [
629 "SELECT `cake`.`id`, `cake`.`name` FROM `cake`",
630 "WHERE `cake`.`id` IN (SELECT `cake_id` FROM `cake_filling`)",
631 ]
632 .join(" ")
633 );
634 }
635
636 #[test]
637 #[cfg(feature = "macros")]
638 fn select_as_1() {
639 use crate::{ActiveModelTrait, ActiveValue, Update};
640
641 mod hello_expanded {
642 use crate as sea_orm;
643 use crate::entity::prelude::*;
644 use crate::sea_query::{Expr, ExprTrait};
645
646 #[derive(Copy, Clone, Default, Debug, DeriveEntity)]
647 pub struct Entity;
648
649 impl EntityName for Entity {
650 fn table_name(&self) -> &'static str {
651 "hello"
652 }
653 }
654
655 #[derive(Clone, Debug, PartialEq, Eq, DeriveModel, DeriveActiveModel)]
656 pub struct Model {
657 pub id: i32,
658 #[sea_orm(enum_name = "One1")]
659 pub one: i32,
660 pub two: i32,
661 #[sea_orm(enum_name = "Three3")]
662 pub three: i32,
663 }
664
665 #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
666 pub enum Column {
667 Id,
668 One1,
669 Two,
670 Three3,
671 }
672
673 impl ColumnTrait for Column {
674 type EntityName = Entity;
675
676 fn def(&self) -> ColumnDef {
677 match self {
678 Column::Id => ColumnType::Integer.def(),
679 Column::One1 => ColumnType::Integer.def(),
680 Column::Two => ColumnType::Integer.def(),
681 Column::Three3 => ColumnType::Integer.def(),
682 }
683 }
684
685 fn select_as(&self, expr: Expr) -> Expr {
686 match self {
687 Self::Two => expr.cast_as("integer"),
688 _ => self.select_enum_as(expr),
689 }
690 }
691 }
692
693 #[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
694 pub enum PrimaryKey {
695 Id,
696 }
697
698 impl PrimaryKeyTrait for PrimaryKey {
699 type ValueType = i32;
700
701 fn auto_increment() -> bool {
702 true
703 }
704 }
705
706 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
707 pub enum Relation {}
708
709 impl ActiveModelBehavior for ActiveModel {}
710 }
711
712 #[allow(clippy::enum_variant_names)]
713 mod hello_compact {
714 use crate as sea_orm;
715 use crate::entity::prelude::*;
716
717 #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
718 #[sea_orm(table_name = "hello")]
719 pub struct Model {
720 #[sea_orm(primary_key)]
721 pub id: i32,
722 #[sea_orm(enum_name = "One1")]
723 pub one: i32,
724 #[sea_orm(select_as = "integer")]
725 pub two: i32,
726 #[sea_orm(enum_name = "Three3")]
727 pub three: i32,
728 }
729
730 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
731 pub enum Relation {}
732
733 impl ActiveModelBehavior for ActiveModel {}
734 }
735
736 fn assert_it<E, A>(active_model: A)
737 where
738 E: EntityTrait,
739 A: ActiveModelTrait<Entity = E>,
740 {
741 assert_eq!(
742 E::find().build(DbBackend::Postgres).to_string(),
743 r#"SELECT "hello"."id", "hello"."one1", CAST("hello"."two" AS integer), "hello"."three3" FROM "hello""#,
744 );
745 assert_eq!(
746 Update::one(active_model)
747 .validate()
748 .unwrap()
749 .build(DbBackend::Postgres)
750 .to_string(),
751 r#"UPDATE "hello" SET "one1" = 1, "two" = 2, "three3" = 3 WHERE "hello"."id" = 1"#,
752 );
753 }
754
755 assert_it(hello_expanded::ActiveModel {
756 id: ActiveValue::set(1),
757 one: ActiveValue::set(1),
758 two: ActiveValue::set(2),
759 three: ActiveValue::set(3),
760 });
761 assert_it(hello_compact::ActiveModel {
762 id: ActiveValue::set(1),
763 one: ActiveValue::set(1),
764 two: ActiveValue::set(2),
765 three: ActiveValue::set(3),
766 });
767 }
768
769 #[test]
770 #[cfg(feature = "macros")]
771 fn save_as_1() {
772 use crate::{ActiveModelTrait, ActiveValue, Update};
773
774 mod hello_expanded {
775 use crate as sea_orm;
776 use crate::entity::prelude::*;
777 use crate::sea_query::{Expr, ExprTrait};
778
779 #[derive(Copy, Clone, Default, Debug, DeriveEntity)]
780 pub struct Entity;
781
782 impl EntityName for Entity {
783 fn table_name(&self) -> &'static str {
784 "hello"
785 }
786 }
787
788 #[derive(Clone, Debug, PartialEq, Eq, DeriveModel, DeriveActiveModel)]
789 pub struct Model {
790 pub id: i32,
791 #[sea_orm(enum_name = "One1")]
792 pub one: i32,
793 pub two: i32,
794 #[sea_orm(enum_name = "Three3")]
795 pub three: i32,
796 }
797
798 #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
799 pub enum Column {
800 Id,
801 One1,
802 Two,
803 Three3,
804 }
805
806 impl ColumnTrait for Column {
807 type EntityName = Entity;
808
809 fn def(&self) -> ColumnDef {
810 match self {
811 Column::Id => ColumnType::Integer.def(),
812 Column::One1 => ColumnType::Integer.def(),
813 Column::Two => ColumnType::Integer.def(),
814 Column::Three3 => ColumnType::Integer.def(),
815 }
816 }
817
818 fn save_as(&self, val: Expr) -> Expr {
819 match self {
820 Self::Two => val.cast_as("text"),
821 _ => self.save_enum_as(val),
822 }
823 }
824 }
825
826 #[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
827 pub enum PrimaryKey {
828 Id,
829 }
830
831 impl PrimaryKeyTrait for PrimaryKey {
832 type ValueType = i32;
833
834 fn auto_increment() -> bool {
835 true
836 }
837 }
838
839 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
840 pub enum Relation {}
841
842 impl ActiveModelBehavior for ActiveModel {}
843 }
844
845 #[allow(clippy::enum_variant_names)]
846 mod hello_compact {
847 use crate as sea_orm;
848 use crate::entity::prelude::*;
849
850 #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
851 #[sea_orm(table_name = "hello")]
852 pub struct Model {
853 #[sea_orm(primary_key)]
854 pub id: i32,
855 #[sea_orm(enum_name = "One1")]
856 pub one: i32,
857 #[sea_orm(save_as = "text")]
858 pub two: i32,
859 #[sea_orm(enum_name = "Three3")]
860 pub three: i32,
861 }
862
863 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
864 pub enum Relation {}
865
866 impl ActiveModelBehavior for ActiveModel {}
867 }
868
869 fn assert_it<E, A>(active_model: A)
870 where
871 E: EntityTrait,
872 A: ActiveModelTrait<Entity = E>,
873 {
874 assert_eq!(
875 E::find().build(DbBackend::Postgres).to_string(),
876 r#"SELECT "hello"."id", "hello"."one1", "hello"."two", "hello"."three3" FROM "hello""#,
877 );
878 assert_eq!(
879 Update::one(active_model)
880 .validate()
881 .unwrap()
882 .build(DbBackend::Postgres)
883 .to_string(),
884 r#"UPDATE "hello" SET "one1" = 1, "two" = CAST(2 AS text), "three3" = 3 WHERE "hello"."id" = 1"#,
885 );
886 }
887
888 assert_it(hello_expanded::ActiveModel {
889 id: ActiveValue::set(1),
890 one: ActiveValue::set(1),
891 two: ActiveValue::set(2),
892 three: ActiveValue::set(3),
893 });
894 assert_it(hello_compact::ActiveModel {
895 id: ActiveValue::set(1),
896 one: ActiveValue::set(1),
897 two: ActiveValue::set(2),
898 three: ActiveValue::set(3),
899 });
900 }
901
902 #[test]
903 #[cfg(feature = "macros")]
904 fn select_as_and_value_1() {
905 use crate::{ActiveModelTrait, ActiveValue, Update};
906
907 mod hello_expanded {
908 use crate as sea_orm;
909 use crate::entity::prelude::*;
910 use crate::sea_query::{Expr, ExprTrait};
911
912 #[derive(Copy, Clone, Default, Debug, DeriveEntity)]
913 pub struct Entity;
914
915 impl EntityName for Entity {
916 fn table_name(&self) -> &'static str {
917 "hello"
918 }
919 }
920
921 #[derive(Clone, Debug, PartialEq, Eq, DeriveModel, DeriveActiveModel)]
922 pub struct Model {
923 pub id: i32,
924 #[sea_orm(enum_name = "One1")]
925 pub one: i32,
926 pub two: i32,
927 #[sea_orm(enum_name = "Three3")]
928 pub three: i32,
929 }
930
931 #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
932 pub enum Column {
933 Id,
934 One1,
935 Two,
936 Three3,
937 }
938
939 impl ColumnTrait for Column {
940 type EntityName = Entity;
941
942 fn def(&self) -> ColumnDef {
943 match self {
944 Column::Id => ColumnType::Integer.def(),
945 Column::One1 => ColumnType::Integer.def(),
946 Column::Two => ColumnType::Integer.def(),
947 Column::Three3 => ColumnType::Integer.def(),
948 }
949 }
950
951 fn select_as(&self, expr: Expr) -> Expr {
952 match self {
953 Self::Two => expr.cast_as("integer"),
954 _ => self.select_enum_as(expr),
955 }
956 }
957
958 fn save_as(&self, val: Expr) -> Expr {
959 match self {
960 Self::Two => val.cast_as("text"),
961 _ => self.save_enum_as(val),
962 }
963 }
964 }
965
966 #[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
967 pub enum PrimaryKey {
968 Id,
969 }
970
971 impl PrimaryKeyTrait for PrimaryKey {
972 type ValueType = i32;
973
974 fn auto_increment() -> bool {
975 true
976 }
977 }
978
979 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
980 pub enum Relation {}
981
982 impl ActiveModelBehavior for ActiveModel {}
983 }
984
985 #[allow(clippy::enum_variant_names)]
986 mod hello_compact {
987 use crate as sea_orm;
988 use crate::entity::prelude::*;
989
990 #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
991 #[sea_orm(table_name = "hello")]
992 pub struct Model {
993 #[sea_orm(primary_key)]
994 pub id: i32,
995 #[sea_orm(enum_name = "One1")]
996 pub one: i32,
997 #[sea_orm(select_as = "integer", save_as = "text")]
998 pub two: i32,
999 #[sea_orm(enum_name = "Three3")]
1000 pub three: i32,
1001 }
1002
1003 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1004 pub enum Relation {}
1005
1006 impl ActiveModelBehavior for ActiveModel {}
1007 }
1008
1009 fn assert_it<E, A>(active_model: A)
1010 where
1011 E: EntityTrait,
1012 A: ActiveModelTrait<Entity = E>,
1013 {
1014 assert_eq!(
1015 E::find().build(DbBackend::Postgres).to_string(),
1016 r#"SELECT "hello"."id", "hello"."one1", CAST("hello"."two" AS integer), "hello"."three3" FROM "hello""#,
1017 );
1018 assert_eq!(
1019 Update::one(active_model)
1020 .validate()
1021 .unwrap()
1022 .build(DbBackend::Postgres)
1023 .to_string(),
1024 r#"UPDATE "hello" SET "one1" = 1, "two" = CAST(2 AS text), "three3" = 3 WHERE "hello"."id" = 1"#,
1025 );
1026 }
1027
1028 assert_it(hello_expanded::ActiveModel {
1029 id: ActiveValue::set(1),
1030 one: ActiveValue::set(1),
1031 two: ActiveValue::set(2),
1032 three: ActiveValue::set(3),
1033 });
1034 assert_it(hello_compact::ActiveModel {
1035 id: ActiveValue::set(1),
1036 one: ActiveValue::set(1),
1037 two: ActiveValue::set(2),
1038 three: ActiveValue::set(3),
1039 });
1040 }
1041}