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<A>(&self, arr: A) -> Expr
65 where
66 A: Into<sea_query::value::Array>,
67 {
68 use sea_query::extension::postgres::PgBinOper;
69
70 let value = Value::Array(arr.into());
71 Expr::col(self.as_column_ref()).binary(PgBinOper::$oper, self.save_as(Expr::val(value)))
72 }
73 };
74 }
75
76 pub(crate) use bind_array_oper;
77 pub(crate) use bind_func_no_params;
78 pub(crate) use bind_oper;
79 pub(crate) use bind_subquery_func;
80 pub(crate) use bind_vec_func;
81}
82
83use macros::*;
84
85pub trait ColumnTrait: IdenStatic + Iterable + FromStr {
87 #[allow(missing_docs)]
88 type EntityName: EntityName;
89
90 fn def(&self) -> ColumnDef;
92
93 fn enum_type_name(&self) -> Option<&'static str> {
95 None
96 }
97
98 fn entity_name(&self) -> DynIden {
100 SeaRc::new(Self::EntityName::default())
101 }
102
103 fn as_column_ref(&self) -> (DynIden, DynIden) {
105 (self.entity_name(), SeaRc::new(*self))
106 }
107
108 fn eq<V>(&self, v: V) -> Expr
128 where
129 V: Into<Value>,
130 {
131 let v = v.into();
132 if v == v.as_null() {
133 Expr::col(self.as_column_ref()).is_null()
134 } else {
135 let expr = self.save_as(Expr::val(v));
136 Expr::col(self.as_column_ref()).eq(expr)
137 }
138 }
139
140 fn ne<V>(&self, v: V) -> Expr
160 where
161 V: Into<Value>,
162 {
163 let v = v.into();
164 if v == v.as_null() {
165 Expr::col(self.as_column_ref()).is_not_null()
166 } else {
167 let expr = self.save_as(Expr::val(v));
168 Expr::col(self.as_column_ref()).ne(expr)
169 }
170 }
171
172 bind_oper!(gt, GreaterThan);
173 bind_oper!(gte, GreaterThanOrEqual);
174 bind_oper!(lt, SmallerThan);
175 bind_oper!(lte, SmallerThanOrEqual);
176
177 fn between<V>(&self, a: V, b: V) -> Expr
189 where
190 V: Into<Value>,
191 {
192 Expr::col(self.as_column_ref()).between(a, b)
193 }
194
195 fn not_between<V>(&self, a: V, b: V) -> Expr
207 where
208 V: Into<Value>,
209 {
210 Expr::col(self.as_column_ref()).not_between(a, b)
211 }
212
213 fn like<T>(&self, s: T) -> Expr
225 where
226 T: IntoLikeExpr,
227 {
228 Expr::col(self.as_column_ref()).like(s)
229 }
230
231 fn not_like<T>(&self, s: T) -> Expr
243 where
244 T: IntoLikeExpr,
245 {
246 Expr::col(self.as_column_ref()).not_like(s)
247 }
248
249 fn ilike<T>(&self, s: T) -> Expr
262 where
263 T: IntoLikeExpr,
264 {
265 use sea_query::extension::postgres::PgExpr;
266
267 Expr::col(self.as_column_ref()).ilike(s)
268 }
269
270 fn not_ilike<T>(&self, s: T) -> Expr
283 where
284 T: IntoLikeExpr,
285 {
286 use sea_query::extension::postgres::PgExpr;
287
288 Expr::col(self.as_column_ref()).not_ilike(s)
289 }
290
291 fn starts_with<T>(&self, s: T) -> Expr
308 where
309 T: Into<String>,
310 {
311 let pattern = format!("{}%", s.into());
312 Expr::col(self.as_column_ref()).like(pattern)
313 }
314
315 fn ends_with<T>(&self, s: T) -> Expr
332 where
333 T: Into<String>,
334 {
335 let pattern = format!("%{}", s.into());
336 Expr::col(self.as_column_ref()).like(pattern)
337 }
338
339 fn contains<T>(&self, s: T) -> Expr
356 where
357 T: Into<String>,
358 {
359 let pattern = format!("%{}%", s.into());
360 Expr::col(self.as_column_ref()).like(pattern)
361 }
362
363 bind_func_no_params!(max);
364 bind_func_no_params!(min);
365 bind_func_no_params!(sum);
366 bind_func_no_params!(avg);
367 bind_func_no_params!(count);
368 bind_func_no_params!(is_null);
369 bind_func_no_params!(is_not_null);
370
371 fn if_null<V>(&self, v: V) -> Expr
373 where
374 V: Into<Value>,
375 {
376 Expr::col(self.as_column_ref()).if_null(v)
377 }
378
379 bind_vec_func!(is_in);
380 bind_vec_func!(is_not_in);
381
382 #[cfg(feature = "postgres-array")]
395 fn eq_any<A>(&self, arr: A) -> Expr
396 where
397 A: Into<sea_query::value::Array>,
398 {
399 use sea_query::extension::postgres::PgFunc;
400
401 let value = Value::Array(arr.into());
402 Expr::col(self.as_column_ref()).eq(PgFunc::any(Expr::val(value)))
403 }
404
405 bind_subquery_func!(in_subquery);
406 bind_subquery_func!(not_in_subquery);
407
408 bind_array_oper!(array_contains, Contains);
409 bind_array_oper!(array_contained, Contained);
410 bind_array_oper!(array_overlap, Overlap);
411
412 fn into_expr(self) -> Expr {
414 self.into_simple_expr()
415 }
416
417 #[allow(clippy::match_single_binding)]
419 fn into_returning_expr(self, db_backend: DbBackend) -> Expr {
420 match db_backend {
421 _ => Expr::col(self),
422 }
423 }
424
425 fn select_as(&self, expr: Expr) -> Expr {
428 self.select_enum_as(expr)
429 }
430
431 fn select_enum_as(&self, expr: Expr) -> Expr {
433 cast_enum_as(expr, &self.def(), select_enum_as)
434 }
435
436 fn save_as(&self, val: Expr) -> Expr {
439 self.save_enum_as(val)
440 }
441
442 fn save_enum_as(&self, val: Expr) -> Expr {
444 cast_enum_as(val, &self.def(), save_enum_as)
445 }
446
447 #[cfg(feature = "with-json")]
449 fn json_key(&self) -> &'static str {
450 self.as_str()
451 }
452}
453
454pub trait ColumnTypeTrait {
456 fn def(self) -> ColumnDef;
458
459 fn get_enum_name(&self) -> Option<&DynIden>;
461}
462
463impl ColumnTypeTrait for ColumnType {
464 fn def(self) -> ColumnDef {
465 ColumnDef {
466 col_type: self,
467 null: false,
468 unique: false,
469 indexed: false,
470 default: None,
471 comment: None,
472 unique_key: None,
473 renamed_from: None,
474 extra: None,
475 seaography: Default::default(),
476 }
477 }
478
479 fn get_enum_name(&self) -> Option<&DynIden> {
480 enum_name(self)
481 }
482}
483
484impl ColumnTypeTrait for ColumnDef {
485 fn def(self) -> ColumnDef {
486 self
487 }
488
489 fn get_enum_name(&self) -> Option<&DynIden> {
490 enum_name(&self.col_type)
491 }
492}
493
494fn enum_name(col_type: &ColumnType) -> Option<&DynIden> {
495 match col_type {
496 ColumnType::Enum { name, .. } => Some(name),
497 ColumnType::Array(col_type) => enum_name(col_type),
498 _ => None,
499 }
500}
501
502struct Text;
503struct TextArray;
504
505impl Iden for Text {
506 fn quoted(&self) -> Cow<'static, str> {
507 Cow::Borrowed("text")
508 }
509
510 fn unquoted(&self) -> &str {
511 match self.quoted() {
512 Cow::Borrowed(s) => s,
513 _ => unreachable!(),
514 }
515 }
516}
517
518impl Iden for TextArray {
519 fn quoted(&self) -> Cow<'static, str> {
520 Cow::Borrowed("text[]")
522 }
523
524 fn unquoted(&self) -> &str {
525 match self.quoted() {
526 Cow::Borrowed(s) => s,
527 _ => unreachable!(),
528 }
529 }
530}
531
532pub(crate) fn select_enum_as(col: Expr, _: DynIden, col_type: &ColumnType) -> Expr {
533 let type_name = match col_type {
534 ColumnType::Array(_) => TextArray.into_iden(),
535 _ => Text.into_iden(),
536 };
537 col.as_enum(type_name)
538}
539
540pub(crate) fn save_enum_as(col: Expr, enum_name: DynIden, col_type: &ColumnType) -> Expr {
541 let type_name = match col_type {
542 ColumnType::Array(_) => format!("{enum_name}[]").into_iden(),
543 _ => enum_name,
544 };
545 col.as_enum(type_name)
546}
547
548pub(crate) fn cast_enum_as<F>(expr: Expr, col_def: &ColumnDef, f: F) -> Expr
549where
550 F: Fn(Expr, DynIden, &ColumnType) -> Expr,
551{
552 let col_type = col_def.get_column_type();
553
554 match col_type {
555 #[cfg(all(feature = "with-json", feature = "postgres-array"))]
556 ColumnType::Json | ColumnType::JsonBinary => {
557 use sea_query::value::{Array, ArrayType};
558 use serde_json::Value as Json;
559
560 match expr {
561 Expr::Value(Value::Array(Array::Json(json_vec))) => {
562 let json_vec: Vec<Json> = json_vec.into_vec().into_iter().flatten().collect();
564 Expr::Value(Value::Json(Some(json_vec.into())))
565 }
566 Expr::Value(Value::Array(Array::Null(ArrayType::Json))) => {
567 Expr::Value(Value::Json(None))
568 }
569 _ => expr,
570 }
571 }
572 _ => match col_type.get_enum_name() {
573 Some(enum_name) => f(expr, enum_name.clone(), col_type),
574 None => expr,
575 },
576 }
577}
578
579#[cfg(test)]
580mod tests {
581 use crate::{
582 ColumnTrait, Condition, DbBackend, EntityTrait, QueryFilter, QueryTrait, tests_cfg::*,
583 };
584 use sea_query::Query;
585
586 #[test]
587 fn test_in_subquery_1() {
588 assert_eq!(
589 cake::Entity::find()
590 .filter(
591 Condition::any().add(
592 cake::Column::Id.in_subquery(
593 Query::select()
594 .expr(cake::Column::Id.max())
595 .from(cake::Entity)
596 .to_owned()
597 )
598 )
599 )
600 .build(DbBackend::MySql)
601 .to_string(),
602 [
603 "SELECT `cake`.`id`, `cake`.`name` FROM `cake`",
604 "WHERE `cake`.`id` IN (SELECT MAX(`cake`.`id`) FROM `cake`)",
605 ]
606 .join(" ")
607 );
608 }
609
610 #[test]
611 fn test_in_subquery_2() {
612 assert_eq!(
613 cake::Entity::find()
614 .filter(
615 Condition::any().add(
616 cake::Column::Id.in_subquery(
617 Query::select()
618 .column(cake_filling::Column::CakeId)
619 .from(cake_filling::Entity)
620 .to_owned()
621 )
622 )
623 )
624 .build(DbBackend::MySql)
625 .to_string(),
626 [
627 "SELECT `cake`.`id`, `cake`.`name` FROM `cake`",
628 "WHERE `cake`.`id` IN (SELECT `cake_id` FROM `cake_filling`)",
629 ]
630 .join(" ")
631 );
632 }
633
634 #[test]
635 #[cfg(feature = "macros")]
636 fn select_as_1() {
637 use crate::{ActiveModelTrait, ActiveValue, Update};
638
639 mod hello_expanded {
640 use crate as sea_orm;
641 use crate::entity::prelude::*;
642 use crate::sea_query::{Expr, ExprTrait};
643
644 #[derive(Copy, Clone, Default, Debug, DeriveEntity)]
645 pub struct Entity;
646
647 impl EntityName for Entity {
648 fn table_name(&self) -> &'static str {
649 "hello"
650 }
651 }
652
653 #[derive(Clone, Debug, PartialEq, Eq, DeriveModel, DeriveActiveModel)]
654 pub struct Model {
655 pub id: i32,
656 #[sea_orm(enum_name = "One1")]
657 pub one: i32,
658 pub two: i32,
659 #[sea_orm(enum_name = "Three3")]
660 pub three: i32,
661 }
662
663 #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
664 pub enum Column {
665 Id,
666 One1,
667 Two,
668 Three3,
669 }
670
671 impl ColumnTrait for Column {
672 type EntityName = Entity;
673
674 fn def(&self) -> ColumnDef {
675 match self {
676 Column::Id => ColumnType::Integer.def(),
677 Column::One1 => ColumnType::Integer.def(),
678 Column::Two => ColumnType::Integer.def(),
679 Column::Three3 => ColumnType::Integer.def(),
680 }
681 }
682
683 fn select_as(&self, expr: Expr) -> Expr {
684 match self {
685 Self::Two => expr.cast_as("integer"),
686 _ => self.select_enum_as(expr),
687 }
688 }
689 }
690
691 #[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
692 pub enum PrimaryKey {
693 Id,
694 }
695
696 impl PrimaryKeyTrait for PrimaryKey {
697 type ValueType = i32;
698
699 fn auto_increment() -> bool {
700 true
701 }
702 }
703
704 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
705 pub enum Relation {}
706
707 impl ActiveModelBehavior for ActiveModel {}
708 }
709
710 #[allow(clippy::enum_variant_names)]
711 mod hello_compact {
712 use crate as sea_orm;
713 use crate::entity::prelude::*;
714
715 #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
716 #[sea_orm(table_name = "hello")]
717 pub struct Model {
718 #[sea_orm(primary_key)]
719 pub id: i32,
720 #[sea_orm(enum_name = "One1")]
721 pub one: i32,
722 #[sea_orm(select_as = "integer")]
723 pub two: i32,
724 #[sea_orm(enum_name = "Three3")]
725 pub three: i32,
726 }
727
728 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
729 pub enum Relation {}
730
731 impl ActiveModelBehavior for ActiveModel {}
732 }
733
734 fn assert_it<E, A>(active_model: A)
735 where
736 E: EntityTrait,
737 A: ActiveModelTrait<Entity = E>,
738 {
739 assert_eq!(
740 E::find().build(DbBackend::Postgres).to_string(),
741 r#"SELECT "hello"."id", "hello"."one1", CAST("hello"."two" AS integer), "hello"."three3" FROM "hello""#,
742 );
743 assert_eq!(
744 Update::one(active_model)
745 .validate()
746 .unwrap()
747 .build(DbBackend::Postgres)
748 .to_string(),
749 r#"UPDATE "hello" SET "one1" = 1, "two" = 2, "three3" = 3 WHERE "hello"."id" = 1"#,
750 );
751 }
752
753 assert_it(hello_expanded::ActiveModel {
754 id: ActiveValue::set(1),
755 one: ActiveValue::set(1),
756 two: ActiveValue::set(2),
757 three: ActiveValue::set(3),
758 });
759 assert_it(hello_compact::ActiveModel {
760 id: ActiveValue::set(1),
761 one: ActiveValue::set(1),
762 two: ActiveValue::set(2),
763 three: ActiveValue::set(3),
764 });
765 }
766
767 #[test]
768 #[cfg(feature = "macros")]
769 fn save_as_1() {
770 use crate::{ActiveModelTrait, ActiveValue, Update};
771
772 mod hello_expanded {
773 use crate as sea_orm;
774 use crate::entity::prelude::*;
775 use crate::sea_query::{Expr, ExprTrait};
776
777 #[derive(Copy, Clone, Default, Debug, DeriveEntity)]
778 pub struct Entity;
779
780 impl EntityName for Entity {
781 fn table_name(&self) -> &'static str {
782 "hello"
783 }
784 }
785
786 #[derive(Clone, Debug, PartialEq, Eq, DeriveModel, DeriveActiveModel)]
787 pub struct Model {
788 pub id: i32,
789 #[sea_orm(enum_name = "One1")]
790 pub one: i32,
791 pub two: i32,
792 #[sea_orm(enum_name = "Three3")]
793 pub three: i32,
794 }
795
796 #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
797 pub enum Column {
798 Id,
799 One1,
800 Two,
801 Three3,
802 }
803
804 impl ColumnTrait for Column {
805 type EntityName = Entity;
806
807 fn def(&self) -> ColumnDef {
808 match self {
809 Column::Id => ColumnType::Integer.def(),
810 Column::One1 => ColumnType::Integer.def(),
811 Column::Two => ColumnType::Integer.def(),
812 Column::Three3 => ColumnType::Integer.def(),
813 }
814 }
815
816 fn save_as(&self, val: Expr) -> Expr {
817 match self {
818 Self::Two => val.cast_as("text"),
819 _ => self.save_enum_as(val),
820 }
821 }
822 }
823
824 #[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
825 pub enum PrimaryKey {
826 Id,
827 }
828
829 impl PrimaryKeyTrait for PrimaryKey {
830 type ValueType = i32;
831
832 fn auto_increment() -> bool {
833 true
834 }
835 }
836
837 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
838 pub enum Relation {}
839
840 impl ActiveModelBehavior for ActiveModel {}
841 }
842
843 #[allow(clippy::enum_variant_names)]
844 mod hello_compact {
845 use crate as sea_orm;
846 use crate::entity::prelude::*;
847
848 #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
849 #[sea_orm(table_name = "hello")]
850 pub struct Model {
851 #[sea_orm(primary_key)]
852 pub id: i32,
853 #[sea_orm(enum_name = "One1")]
854 pub one: i32,
855 #[sea_orm(save_as = "text")]
856 pub two: i32,
857 #[sea_orm(enum_name = "Three3")]
858 pub three: i32,
859 }
860
861 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
862 pub enum Relation {}
863
864 impl ActiveModelBehavior for ActiveModel {}
865 }
866
867 fn assert_it<E, A>(active_model: A)
868 where
869 E: EntityTrait,
870 A: ActiveModelTrait<Entity = E>,
871 {
872 assert_eq!(
873 E::find().build(DbBackend::Postgres).to_string(),
874 r#"SELECT "hello"."id", "hello"."one1", "hello"."two", "hello"."three3" FROM "hello""#,
875 );
876 assert_eq!(
877 Update::one(active_model)
878 .validate()
879 .unwrap()
880 .build(DbBackend::Postgres)
881 .to_string(),
882 r#"UPDATE "hello" SET "one1" = 1, "two" = CAST(2 AS text), "three3" = 3 WHERE "hello"."id" = 1"#,
883 );
884 }
885
886 assert_it(hello_expanded::ActiveModel {
887 id: ActiveValue::set(1),
888 one: ActiveValue::set(1),
889 two: ActiveValue::set(2),
890 three: ActiveValue::set(3),
891 });
892 assert_it(hello_compact::ActiveModel {
893 id: ActiveValue::set(1),
894 one: ActiveValue::set(1),
895 two: ActiveValue::set(2),
896 three: ActiveValue::set(3),
897 });
898 }
899
900 #[test]
901 #[cfg(feature = "macros")]
902 fn select_as_and_value_1() {
903 use crate::{ActiveModelTrait, ActiveValue, Update};
904
905 mod hello_expanded {
906 use crate as sea_orm;
907 use crate::entity::prelude::*;
908 use crate::sea_query::{Expr, ExprTrait};
909
910 #[derive(Copy, Clone, Default, Debug, DeriveEntity)]
911 pub struct Entity;
912
913 impl EntityName for Entity {
914 fn table_name(&self) -> &'static str {
915 "hello"
916 }
917 }
918
919 #[derive(Clone, Debug, PartialEq, Eq, DeriveModel, DeriveActiveModel)]
920 pub struct Model {
921 pub id: i32,
922 #[sea_orm(enum_name = "One1")]
923 pub one: i32,
924 pub two: i32,
925 #[sea_orm(enum_name = "Three3")]
926 pub three: i32,
927 }
928
929 #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
930 pub enum Column {
931 Id,
932 One1,
933 Two,
934 Three3,
935 }
936
937 impl ColumnTrait for Column {
938 type EntityName = Entity;
939
940 fn def(&self) -> ColumnDef {
941 match self {
942 Column::Id => ColumnType::Integer.def(),
943 Column::One1 => ColumnType::Integer.def(),
944 Column::Two => ColumnType::Integer.def(),
945 Column::Three3 => ColumnType::Integer.def(),
946 }
947 }
948
949 fn select_as(&self, expr: Expr) -> Expr {
950 match self {
951 Self::Two => expr.cast_as("integer"),
952 _ => self.select_enum_as(expr),
953 }
954 }
955
956 fn save_as(&self, val: Expr) -> Expr {
957 match self {
958 Self::Two => val.cast_as("text"),
959 _ => self.save_enum_as(val),
960 }
961 }
962 }
963
964 #[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
965 pub enum PrimaryKey {
966 Id,
967 }
968
969 impl PrimaryKeyTrait for PrimaryKey {
970 type ValueType = i32;
971
972 fn auto_increment() -> bool {
973 true
974 }
975 }
976
977 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
978 pub enum Relation {}
979
980 impl ActiveModelBehavior for ActiveModel {}
981 }
982
983 #[allow(clippy::enum_variant_names)]
984 mod hello_compact {
985 use crate as sea_orm;
986 use crate::entity::prelude::*;
987
988 #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
989 #[sea_orm(table_name = "hello")]
990 pub struct Model {
991 #[sea_orm(primary_key)]
992 pub id: i32,
993 #[sea_orm(enum_name = "One1")]
994 pub one: i32,
995 #[sea_orm(select_as = "integer", save_as = "text")]
996 pub two: i32,
997 #[sea_orm(enum_name = "Three3")]
998 pub three: i32,
999 }
1000
1001 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1002 pub enum Relation {}
1003
1004 impl ActiveModelBehavior for ActiveModel {}
1005 }
1006
1007 fn assert_it<E, A>(active_model: A)
1008 where
1009 E: EntityTrait,
1010 A: ActiveModelTrait<Entity = E>,
1011 {
1012 assert_eq!(
1013 E::find().build(DbBackend::Postgres).to_string(),
1014 r#"SELECT "hello"."id", "hello"."one1", CAST("hello"."two" AS integer), "hello"."three3" FROM "hello""#,
1015 );
1016 assert_eq!(
1017 Update::one(active_model)
1018 .validate()
1019 .unwrap()
1020 .build(DbBackend::Postgres)
1021 .to_string(),
1022 r#"UPDATE "hello" SET "one1" = 1, "two" = CAST(2 AS text), "three3" = 3 WHERE "hello"."id" = 1"#,
1023 );
1024 }
1025
1026 assert_it(hello_expanded::ActiveModel {
1027 id: ActiveValue::set(1),
1028 one: ActiveValue::set(1),
1029 two: ActiveValue::set(2),
1030 three: ActiveValue::set(3),
1031 });
1032 assert_it(hello_compact::ActiveModel {
1033 id: ActiveValue::set(1),
1034 one: ActiveValue::set(1),
1035 two: ActiveValue::set(2),
1036 three: ActiveValue::set(3),
1037 });
1038 }
1039}