1use crate::{DbBackend, EntityName, Iden, IdenStatic, IntoSimpleExpr, Iterable};
2use sea_query::{
3 Alias, BinOper, DynIden, Expr, IntoIden, IntoLikeExpr, SeaRc, SelectStatement, SimpleExpr,
4 Value,
5};
6use std::str::FromStr;
7
8pub use sea_query::ColumnType;
11
12#[derive(Debug, Clone, PartialEq)]
14pub struct ColumnDef {
15 pub(crate) col_type: ColumnType,
16 pub(crate) null: bool,
17 pub(crate) unique: bool,
18 pub(crate) indexed: bool,
19 pub(crate) default: Option<SimpleExpr>,
20 pub(crate) comment: Option<String>,
21}
22
23macro_rules! bind_oper {
24 ( $op: ident, $bin_op: ident ) => {
25 #[allow(missing_docs)]
26 fn $op<V>(&self, v: V) -> SimpleExpr
27 where
28 V: Into<Value>,
29 {
30 let expr = self.save_as(Expr::val(v));
31 Expr::col((self.entity_name(), *self)).binary(BinOper::$bin_op, expr)
32 }
33 };
34}
35
36macro_rules! bind_func_no_params {
37 ( $func: ident ) => {
38 fn $func(&self) -> SimpleExpr {
40 Expr::col((self.entity_name(), *self)).$func()
41 }
42 };
43}
44
45macro_rules! bind_vec_func {
46 ( $func: ident ) => {
47 #[allow(missing_docs)]
48 #[allow(clippy::wrong_self_convention)]
49 fn $func<V, I>(&self, v: I) -> SimpleExpr
50 where
51 V: Into<Value>,
52 I: IntoIterator<Item = V>,
53 {
54 let v_with_enum_cast = v.into_iter().map(|v| self.save_as(Expr::val(v)));
55 Expr::col((self.entity_name(), *self)).$func(v_with_enum_cast)
56 }
57 };
58}
59
60macro_rules! bind_subquery_func {
61 ( $func: ident ) => {
62 #[allow(clippy::wrong_self_convention)]
63 #[allow(missing_docs)]
64 fn $func(&self, s: SelectStatement) -> SimpleExpr {
65 Expr::col((self.entity_name(), *self)).$func(s)
66 }
67 };
68}
69
70pub trait ColumnTrait: IdenStatic + Iterable + FromStr {
73 #[allow(missing_docs)]
74 type EntityName: EntityName;
75
76 fn def(&self) -> ColumnDef;
78
79 fn enum_type_name(&self) -> Option<&'static str> {
81 None
82 }
83
84 fn entity_name(&self) -> DynIden {
86 SeaRc::new(Self::EntityName::default()) as DynIden
87 }
88
89 fn as_column_ref(&self) -> (DynIden, DynIden) {
91 (self.entity_name(), SeaRc::new(*self) as DynIden)
92 }
93
94 bind_oper!(eq, Equal);
95 bind_oper!(ne, NotEqual);
96 bind_oper!(gt, GreaterThan);
97 bind_oper!(gte, GreaterThanOrEqual);
98 bind_oper!(lt, SmallerThan);
99 bind_oper!(lte, SmallerThanOrEqual);
100
101 fn between<V>(&self, a: V, b: V) -> SimpleExpr
113 where
114 V: Into<Value>,
115 {
116 Expr::col((self.entity_name(), *self)).between(a, b)
117 }
118
119 fn not_between<V>(&self, a: V, b: V) -> SimpleExpr
131 where
132 V: Into<Value>,
133 {
134 Expr::col((self.entity_name(), *self)).not_between(a, b)
135 }
136
137 fn like<T>(&self, s: T) -> SimpleExpr
149 where
150 T: IntoLikeExpr,
151 {
152 Expr::col((self.entity_name(), *self)).like(s)
153 }
154
155 fn not_like<T>(&self, s: T) -> SimpleExpr
167 where
168 T: IntoLikeExpr,
169 {
170 Expr::col((self.entity_name(), *self)).not_like(s)
171 }
172
173 fn starts_with<T>(&self, s: T) -> SimpleExpr
190 where
191 T: Into<String>,
192 {
193 let pattern = format!("{}%", s.into());
194 Expr::col((self.entity_name(), *self)).like(pattern)
195 }
196
197 fn ends_with<T>(&self, s: T) -> SimpleExpr
214 where
215 T: Into<String>,
216 {
217 let pattern = format!("%{}", s.into());
218 Expr::col((self.entity_name(), *self)).like(pattern)
219 }
220
221 fn contains<T>(&self, s: T) -> SimpleExpr
238 where
239 T: Into<String>,
240 {
241 let pattern = format!("%{}%", s.into());
242 Expr::col((self.entity_name(), *self)).like(pattern)
243 }
244
245 bind_func_no_params!(max);
246 bind_func_no_params!(min);
247 bind_func_no_params!(sum);
248 bind_func_no_params!(count);
249 bind_func_no_params!(is_null);
250 bind_func_no_params!(is_not_null);
251
252 fn if_null<V>(&self, v: V) -> SimpleExpr
254 where
255 V: Into<Value>,
256 {
257 Expr::col((self.entity_name(), *self)).if_null(v)
258 }
259
260 bind_vec_func!(is_in);
261 bind_vec_func!(is_not_in);
262
263 bind_subquery_func!(in_subquery);
264 bind_subquery_func!(not_in_subquery);
265
266 fn into_expr(self) -> Expr {
268 Expr::expr(self.into_simple_expr())
269 }
270
271 #[allow(clippy::match_single_binding)]
273 fn into_returning_expr(self, db_backend: DbBackend) -> Expr {
274 match db_backend {
275 _ => Expr::col(self),
276 }
277 }
278
279 fn select_as(&self, expr: Expr) -> SimpleExpr {
282 self.select_enum_as(expr)
283 }
284
285 fn select_enum_as(&self, expr: Expr) -> SimpleExpr {
287 cast_enum_as(expr, self, |col, _, col_type| {
288 let type_name = match col_type {
289 ColumnType::Array(_) => TextArray.into_iden(),
290 _ => Text.into_iden(),
291 };
292 col.as_enum(type_name)
293 })
294 }
295
296 fn save_as(&self, val: Expr) -> SimpleExpr {
299 self.save_enum_as(val)
300 }
301
302 fn save_enum_as(&self, val: Expr) -> SimpleExpr {
305 cast_enum_as(val, self, |col, enum_name, col_type| {
306 let type_name = match col_type {
307 ColumnType::Array(_) => {
308 Alias::new(format!("{}[]", enum_name.to_string())).into_iden()
309 }
310 _ => enum_name,
311 };
312 col.as_enum(type_name)
313 })
314 }
315}
316
317pub trait ColumnTypeTrait {
319 fn def(self) -> ColumnDef;
321
322 fn get_enum_name(&self) -> Option<&DynIden>;
324}
325
326impl ColumnTypeTrait for ColumnType {
327 fn def(self) -> ColumnDef {
328 ColumnDef {
329 col_type: self,
330 null: false,
331 unique: false,
332 indexed: false,
333 default: None,
334 comment: None,
335 }
336 }
337
338 fn get_enum_name(&self) -> Option<&DynIden> {
339 enum_name(self)
340 }
341}
342
343impl ColumnTypeTrait for ColumnDef {
344 fn def(self) -> ColumnDef {
345 self
346 }
347
348 fn get_enum_name(&self) -> Option<&DynIden> {
349 enum_name(&self.col_type)
350 }
351}
352
353fn enum_name(col_type: &ColumnType) -> Option<&DynIden> {
354 match col_type {
355 ColumnType::Enum { name, .. } => Some(name),
356 ColumnType::Array(col_type) => enum_name(col_type),
357 _ => None,
358 }
359}
360
361impl ColumnDef {
362 pub fn unique(mut self) -> Self {
364 self.unique = true;
365 self
366 }
367 pub fn comment(mut self, v: &str) -> Self {
369 self.comment = Some(v.into());
370 self
371 }
372
373 pub fn null(self) -> Self {
375 self.nullable()
376 }
377
378 pub fn nullable(mut self) -> Self {
380 self.null = true;
381 self
382 }
383
384 pub fn indexed(mut self) -> Self {
386 self.indexed = true;
387 self
388 }
389
390 pub fn default_value<T>(mut self, value: T) -> Self
392 where
393 T: Into<Value>,
394 {
395 self.default = Some(value.into().into());
396 self
397 }
398
399 pub fn default<T>(mut self, default: T) -> Self
401 where
402 T: Into<SimpleExpr>,
403 {
404 self.default = Some(default.into());
405 self
406 }
407
408 pub fn get_column_type(&self) -> &ColumnType {
410 &self.col_type
411 }
412
413 pub fn get_column_default(&self) -> Option<&SimpleExpr> {
415 self.default.as_ref()
416 }
417
418 pub fn is_null(&self) -> bool {
420 self.null
421 }
422
423 pub fn is_unique(&self) -> bool {
425 self.unique
426 }
427}
428
429struct Text;
430struct TextArray;
431
432impl Iden for Text {
433 fn unquoted(&self, s: &mut dyn std::fmt::Write) {
434 write!(s, "text").unwrap();
435 }
436}
437
438impl Iden for TextArray {
439 fn unquoted(&self, s: &mut dyn std::fmt::Write) {
440 write!(s, "text[]").unwrap();
441 }
442}
443
444fn cast_enum_as<C, F>(expr: Expr, col: &C, f: F) -> SimpleExpr
445where
446 C: ColumnTrait,
447 F: Fn(Expr, DynIden, &ColumnType) -> SimpleExpr,
448{
449 let col_def = col.def();
450 let col_type = col_def.get_column_type();
451
452 match col_type {
453 #[cfg(all(feature = "with-json", feature = "postgres-array"))]
454 ColumnType::Json | ColumnType::JsonBinary => {
455 use sea_query::ArrayType;
456 use serde_json::Value as Json;
457
458 #[allow(clippy::boxed_local)]
459 fn unbox<T>(boxed: Box<T>) -> T {
460 *boxed
461 }
462
463 let expr = expr.into();
464 match expr {
465 SimpleExpr::Value(Value::Array(ArrayType::Json, Some(json_vec))) => {
466 let json_vec: Vec<Json> = json_vec
468 .into_iter()
469 .filter_map(|val| match val {
470 Value::Json(Some(json)) => Some(unbox(json)),
471 _ => None,
472 })
473 .collect();
474 SimpleExpr::Value(Value::Json(Some(Box::new(json_vec.into()))))
475 }
476 SimpleExpr::Value(Value::Array(ArrayType::Json, None)) => {
477 SimpleExpr::Value(Value::Json(None))
478 }
479 _ => expr,
480 }
481 }
482 _ => match col_type.get_enum_name() {
483 Some(enum_name) => f(expr, SeaRc::clone(enum_name), col_type),
484 None => expr.into(),
485 },
486 }
487}
488
489#[cfg(test)]
490mod tests {
491 use crate::{
492 tests_cfg::*, ColumnTrait, Condition, DbBackend, EntityTrait, QueryFilter, QueryTrait,
493 };
494 use sea_query::Query;
495
496 #[test]
497 fn test_in_subquery_1() {
498 assert_eq!(
499 cake::Entity::find()
500 .filter(
501 Condition::any().add(
502 cake::Column::Id.in_subquery(
503 Query::select()
504 .expr(cake::Column::Id.max())
505 .from(cake::Entity)
506 .to_owned()
507 )
508 )
509 )
510 .build(DbBackend::MySql)
511 .to_string(),
512 [
513 "SELECT `cake`.`id`, `cake`.`name` FROM `cake`",
514 "WHERE `cake`.`id` IN (SELECT MAX(`cake`.`id`) FROM `cake`)",
515 ]
516 .join(" ")
517 );
518 }
519
520 #[test]
521 fn test_in_subquery_2() {
522 assert_eq!(
523 cake::Entity::find()
524 .filter(
525 Condition::any().add(
526 cake::Column::Id.in_subquery(
527 Query::select()
528 .column(cake_filling::Column::CakeId)
529 .from(cake_filling::Entity)
530 .to_owned()
531 )
532 )
533 )
534 .build(DbBackend::MySql)
535 .to_string(),
536 [
537 "SELECT `cake`.`id`, `cake`.`name` FROM `cake`",
538 "WHERE `cake`.`id` IN (SELECT `cake_id` FROM `cake_filling`)",
539 ]
540 .join(" ")
541 );
542 }
543
544 #[test]
545 fn test_col_from_str() {
546 use std::str::FromStr;
547
548 assert!(matches!(
549 fruit::Column::from_str("id"),
550 Ok(fruit::Column::Id)
551 ));
552 assert!(matches!(
553 fruit::Column::from_str("name"),
554 Ok(fruit::Column::Name)
555 ));
556 assert!(matches!(
557 fruit::Column::from_str("cake_id"),
558 Ok(fruit::Column::CakeId)
559 ));
560 assert!(matches!(
561 fruit::Column::from_str("cakeId"),
562 Ok(fruit::Column::CakeId)
563 ));
564 assert!(matches!(
565 fruit::Column::from_str("does_not_exist"),
566 Err(crate::ColumnFromStrErr(_))
567 ));
568 }
569
570 #[test]
571 #[cfg(feature = "macros")]
572 fn entity_model_column_1() {
573 use crate::prelude::*;
574
575 mod hello {
576 use crate as sea_orm;
577 use crate::entity::prelude::*;
578
579 #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
580 #[sea_orm(table_name = "hello")]
581 pub struct Model {
582 #[sea_orm(primary_key)]
583 pub id: i32,
584 pub one: i32,
585 #[sea_orm(unique)]
586 pub two: i8,
587 #[sea_orm(indexed)]
588 pub three: i16,
589 #[sea_orm(nullable)]
590 pub four: i32,
591 #[sea_orm(unique, indexed, nullable)]
592 pub five: i64,
593 #[sea_orm(unique)]
594 pub six: u8,
595 #[sea_orm(indexed)]
596 pub seven: u16,
597 #[sea_orm(nullable)]
598 pub eight: u32,
599 #[sea_orm(unique, indexed, nullable)]
600 pub nine: u64,
601 #[sea_orm(default_expr = "Expr::current_timestamp()")]
602 pub ten: DateTimeUtc,
603 #[sea_orm(default_value = 7)]
604 pub eleven: u8,
605 #[sea_orm(default_value = "twelve_value")]
606 pub twelve: String,
607 #[sea_orm(default_expr = "\"twelve_value\"")]
608 pub twelve_two: String,
609 }
610
611 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
612 pub enum Relation {}
613
614 impl ActiveModelBehavior for ActiveModel {}
615 }
616
617 assert_eq!(hello::Column::One.def(), ColumnType::Integer.def());
618 assert_eq!(
619 hello::Column::Two.def(),
620 ColumnType::TinyInteger.def().unique()
621 );
622 assert_eq!(
623 hello::Column::Three.def(),
624 ColumnType::SmallInteger.def().indexed()
625 );
626 assert_eq!(
627 hello::Column::Four.def(),
628 ColumnType::Integer.def().nullable()
629 );
630 assert_eq!(
631 hello::Column::Five.def(),
632 ColumnType::BigInteger.def().unique().indexed().nullable()
633 );
634 assert_eq!(
635 hello::Column::Six.def(),
636 ColumnType::TinyUnsigned.def().unique()
637 );
638 assert_eq!(
639 hello::Column::Seven.def(),
640 ColumnType::SmallUnsigned.def().indexed()
641 );
642 assert_eq!(
643 hello::Column::Eight.def(),
644 ColumnType::Unsigned.def().nullable()
645 );
646 assert_eq!(
647 hello::Column::Nine.def(),
648 ColumnType::BigUnsigned.def().unique().indexed().nullable()
649 );
650 assert_eq!(
651 hello::Column::Ten.def(),
652 ColumnType::TimestampWithTimeZone
653 .def()
654 .default(Expr::current_timestamp())
655 );
656 assert_eq!(
657 hello::Column::Eleven.def(),
658 ColumnType::TinyUnsigned.def().default(7)
659 );
660 assert_eq!(
661 hello::Column::Twelve.def(),
662 ColumnType::String(StringLen::None)
663 .def()
664 .default("twelve_value")
665 );
666 assert_eq!(
667 hello::Column::TwelveTwo.def(),
668 ColumnType::String(StringLen::None)
669 .def()
670 .default("twelve_value")
671 );
672 }
673
674 #[test]
675 #[cfg(feature = "macros")]
676 fn column_name_1() {
677 use sea_query::Iden;
678
679 mod hello {
680 use crate as sea_orm;
681 use crate::entity::prelude::*;
682
683 #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
684 #[sea_orm(table_name = "hello")]
685 pub struct Model {
686 #[sea_orm(primary_key)]
687 pub id: i32,
688 #[sea_orm(column_name = "ONE")]
689 pub one: i32,
690 pub two: i32,
691 #[sea_orm(column_name = "3")]
692 pub three: i32,
693 }
694
695 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
696 pub enum Relation {}
697
698 impl ActiveModelBehavior for ActiveModel {}
699 }
700
701 assert_eq!(hello::Column::One.to_string().as_str(), "ONE");
702 assert_eq!(hello::Column::Two.to_string().as_str(), "two");
703 assert_eq!(hello::Column::Three.to_string().as_str(), "3");
704 }
705
706 #[test]
707 #[cfg(feature = "macros")]
708 fn column_name_2() {
709 use sea_query::Iden;
710
711 mod hello {
712 use crate as sea_orm;
713 use crate::entity::prelude::*;
714
715 #[derive(Copy, Clone, Default, Debug, DeriveEntity)]
716 pub struct Entity;
717
718 impl EntityName for Entity {
719 fn table_name(&self) -> &str {
720 "hello"
721 }
722 }
723
724 #[derive(Clone, Debug, PartialEq, Eq, DeriveModel, DeriveActiveModel)]
725 pub struct Model {
726 pub id: i32,
727 pub one: i32,
728 pub two: i32,
729 pub three: i32,
730 }
731
732 #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
733 pub enum Column {
734 Id,
735 #[sea_orm(column_name = "ONE")]
736 One,
737 Two,
738 #[sea_orm(column_name = "3")]
739 Three,
740 }
741
742 impl ColumnTrait for Column {
743 type EntityName = Entity;
744
745 fn def(&self) -> ColumnDef {
746 match self {
747 Column::Id => ColumnType::Integer.def(),
748 Column::One => ColumnType::Integer.def(),
749 Column::Two => ColumnType::Integer.def(),
750 Column::Three => ColumnType::Integer.def(),
751 }
752 }
753 }
754
755 #[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
756 pub enum PrimaryKey {
757 Id,
758 }
759
760 impl PrimaryKeyTrait for PrimaryKey {
761 type ValueType = i32;
762
763 fn auto_increment() -> bool {
764 true
765 }
766 }
767
768 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
769 pub enum Relation {}
770
771 impl ActiveModelBehavior for ActiveModel {}
772 }
773
774 assert_eq!(hello::Column::One.to_string().as_str(), "ONE");
775 assert_eq!(hello::Column::Two.to_string().as_str(), "two");
776 assert_eq!(hello::Column::Three.to_string().as_str(), "3");
777 }
778
779 #[test]
780 #[cfg(feature = "macros")]
781 fn enum_name_1() {
782 use sea_query::Iden;
783
784 mod hello {
785 use crate as sea_orm;
786 use crate::entity::prelude::*;
787
788 #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
789 #[sea_orm(table_name = "hello")]
790 pub struct Model {
791 #[sea_orm(primary_key)]
792 pub id: i32,
793 #[sea_orm(enum_name = "One1")]
794 pub one: i32,
795 pub two: i32,
796 #[sea_orm(enum_name = "Three3")]
797 pub three: i32,
798 }
799
800 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
801 pub enum Relation {}
802
803 impl ActiveModelBehavior for ActiveModel {}
804 }
805
806 assert_eq!(hello::Column::One1.to_string().as_str(), "one1");
807 assert_eq!(hello::Column::Two.to_string().as_str(), "two");
808 assert_eq!(hello::Column::Three3.to_string().as_str(), "three3");
809 }
810
811 #[test]
812 #[cfg(feature = "macros")]
813 fn enum_name_2() {
814 use sea_query::Iden;
815
816 mod hello {
817 use crate as sea_orm;
818 use crate::entity::prelude::*;
819
820 #[derive(Copy, Clone, Default, Debug, DeriveEntity)]
821 pub struct Entity;
822
823 impl EntityName for Entity {
824 fn table_name(&self) -> &str {
825 "hello"
826 }
827 }
828
829 #[derive(Clone, Debug, PartialEq, Eq, DeriveModel, DeriveActiveModel)]
830 pub struct Model {
831 pub id: i32,
832 #[sea_orm(enum_name = "One1")]
833 pub one: i32,
834 pub two: i32,
835 #[sea_orm(enum_name = "Three3")]
836 pub three: i32,
837 }
838
839 #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
840 pub enum Column {
841 Id,
842 One1,
843 Two,
844 Three3,
845 }
846
847 impl ColumnTrait for Column {
848 type EntityName = Entity;
849
850 fn def(&self) -> ColumnDef {
851 match self {
852 Column::Id => ColumnType::Integer.def(),
853 Column::One1 => ColumnType::Integer.def(),
854 Column::Two => ColumnType::Integer.def(),
855 Column::Three3 => ColumnType::Integer.def(),
856 }
857 }
858 }
859
860 #[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
861 pub enum PrimaryKey {
862 Id,
863 }
864
865 impl PrimaryKeyTrait for PrimaryKey {
866 type ValueType = i32;
867
868 fn auto_increment() -> bool {
869 true
870 }
871 }
872
873 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
874 pub enum Relation {}
875
876 impl ActiveModelBehavior for ActiveModel {}
877 }
878
879 assert_eq!(hello::Column::One1.to_string().as_str(), "one1");
880 assert_eq!(hello::Column::Two.to_string().as_str(), "two");
881 assert_eq!(hello::Column::Three3.to_string().as_str(), "three3");
882 }
883
884 #[test]
885 #[cfg(feature = "macros")]
886 fn column_name_enum_name_1() {
887 use sea_query::Iden;
888
889 #[allow(clippy::enum_variant_names)]
890 mod hello {
891 use crate as sea_orm;
892 use crate::entity::prelude::*;
893
894 #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
895 #[sea_orm(table_name = "hello")]
896 pub struct Model {
897 #[sea_orm(primary_key, column_name = "ID", enum_name = "IdentityColumn")]
898 pub id: i32,
899 #[sea_orm(column_name = "ONE", enum_name = "One1")]
900 pub one: i32,
901 pub two: i32,
902 #[sea_orm(column_name = "THREE", enum_name = "Three3")]
903 pub three: i32,
904 }
905
906 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
907 pub enum Relation {}
908
909 impl ActiveModelBehavior for ActiveModel {}
910 }
911
912 assert_eq!(hello::Column::IdentityColumn.to_string().as_str(), "ID");
913 assert_eq!(hello::Column::One1.to_string().as_str(), "ONE");
914 assert_eq!(hello::Column::Two.to_string().as_str(), "two");
915 assert_eq!(hello::Column::Three3.to_string().as_str(), "THREE");
916 }
917
918 #[test]
919 #[cfg(feature = "macros")]
920 fn column_name_enum_name_2() {
921 use sea_query::Iden;
922
923 mod hello {
924 use crate as sea_orm;
925 use crate::entity::prelude::*;
926
927 #[derive(Copy, Clone, Default, Debug, DeriveEntity)]
928 pub struct Entity;
929
930 impl EntityName for Entity {
931 fn table_name(&self) -> &str {
932 "hello"
933 }
934 }
935
936 #[derive(Clone, Debug, PartialEq, Eq, DeriveModel, DeriveActiveModel)]
937 pub struct Model {
938 #[sea_orm(enum_name = "IdentityCol")]
939 pub id: i32,
940 #[sea_orm(enum_name = "One1")]
941 pub one: i32,
942 pub two: i32,
943 #[sea_orm(enum_name = "Three3")]
944 pub three: i32,
945 }
946
947 #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
948 pub enum Column {
949 #[sea_orm(column_name = "ID")]
950 IdentityCol,
951 #[sea_orm(column_name = "ONE")]
952 One1,
953 Two,
954 #[sea_orm(column_name = "THREE")]
955 Three3,
956 }
957
958 impl ColumnTrait for Column {
959 type EntityName = Entity;
960
961 fn def(&self) -> ColumnDef {
962 match self {
963 Column::IdentityCol => ColumnType::Integer.def(),
964 Column::One1 => ColumnType::Integer.def(),
965 Column::Two => ColumnType::Integer.def(),
966 Column::Three3 => ColumnType::Integer.def(),
967 }
968 }
969 }
970
971 #[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
972 pub enum PrimaryKey {
973 IdentityCol,
974 }
975
976 impl PrimaryKeyTrait for PrimaryKey {
977 type ValueType = i32;
978
979 fn auto_increment() -> bool {
980 true
981 }
982 }
983
984 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
985 pub enum Relation {}
986
987 impl ActiveModelBehavior for ActiveModel {}
988 }
989
990 assert_eq!(hello::Column::IdentityCol.to_string().as_str(), "ID");
991 assert_eq!(hello::Column::One1.to_string().as_str(), "ONE");
992 assert_eq!(hello::Column::Two.to_string().as_str(), "two");
993 assert_eq!(hello::Column::Three3.to_string().as_str(), "THREE");
994 }
995
996 #[test]
997 #[cfg(feature = "macros")]
998 fn column_name_enum_name_3() {
999 use sea_query::Iden;
1000
1001 mod my_entity {
1002 use crate as sea_orm;
1003 use crate::entity::prelude::*;
1004
1005 #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
1006 #[sea_orm(table_name = "my_entity")]
1007 pub struct Model {
1008 #[sea_orm(primary_key, enum_name = "IdentityColumn", column_name = "id")]
1009 pub id: i32,
1010 #[sea_orm(column_name = "type")]
1011 pub type_: String,
1012 }
1013
1014 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1015 pub enum Relation {}
1016
1017 impl ActiveModelBehavior for ActiveModel {}
1018 }
1019
1020 assert_eq!(my_entity::Column::IdentityColumn.to_string().as_str(), "id");
1021 assert_eq!(my_entity::Column::Type.to_string().as_str(), "type");
1022 }
1023
1024 #[test]
1025 #[cfg(feature = "macros")]
1026 fn select_as_1() {
1027 use crate::{ActiveModelTrait, ActiveValue, Update};
1028
1029 mod hello_expanded {
1030 use crate as sea_orm;
1031 use crate::entity::prelude::*;
1032 use crate::sea_query::{Expr, SimpleExpr};
1033
1034 #[derive(Copy, Clone, Default, Debug, DeriveEntity)]
1035 pub struct Entity;
1036
1037 impl EntityName for Entity {
1038 fn table_name(&self) -> &str {
1039 "hello"
1040 }
1041 }
1042
1043 #[derive(Clone, Debug, PartialEq, Eq, DeriveModel, DeriveActiveModel)]
1044 pub struct Model {
1045 pub id: i32,
1046 #[sea_orm(enum_name = "One1")]
1047 pub one: i32,
1048 pub two: i32,
1049 #[sea_orm(enum_name = "Three3")]
1050 pub three: i32,
1051 }
1052
1053 #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
1054 pub enum Column {
1055 Id,
1056 One1,
1057 Two,
1058 Three3,
1059 }
1060
1061 impl ColumnTrait for Column {
1062 type EntityName = Entity;
1063
1064 fn def(&self) -> ColumnDef {
1065 match self {
1066 Column::Id => ColumnType::Integer.def(),
1067 Column::One1 => ColumnType::Integer.def(),
1068 Column::Two => ColumnType::Integer.def(),
1069 Column::Three3 => ColumnType::Integer.def(),
1070 }
1071 }
1072
1073 fn select_as(&self, expr: Expr) -> SimpleExpr {
1074 match self {
1075 Self::Two => expr.cast_as("integer"),
1076 _ => self.select_enum_as(expr),
1077 }
1078 }
1079 }
1080
1081 #[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
1082 pub enum PrimaryKey {
1083 Id,
1084 }
1085
1086 impl PrimaryKeyTrait for PrimaryKey {
1087 type ValueType = i32;
1088
1089 fn auto_increment() -> bool {
1090 true
1091 }
1092 }
1093
1094 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1095 pub enum Relation {}
1096
1097 impl ActiveModelBehavior for ActiveModel {}
1098 }
1099
1100 #[allow(clippy::enum_variant_names)]
1101 mod hello_compact {
1102 use crate as sea_orm;
1103 use crate::entity::prelude::*;
1104
1105 #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
1106 #[sea_orm(table_name = "hello")]
1107 pub struct Model {
1108 #[sea_orm(primary_key)]
1109 pub id: i32,
1110 #[sea_orm(enum_name = "One1")]
1111 pub one: i32,
1112 #[sea_orm(select_as = "integer")]
1113 pub two: i32,
1114 #[sea_orm(enum_name = "Three3")]
1115 pub three: i32,
1116 }
1117
1118 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1119 pub enum Relation {}
1120
1121 impl ActiveModelBehavior for ActiveModel {}
1122 }
1123
1124 fn assert_it<E, A>(active_model: A)
1125 where
1126 E: EntityTrait,
1127 A: ActiveModelTrait<Entity = E>,
1128 {
1129 assert_eq!(
1130 E::find().build(DbBackend::Postgres).to_string(),
1131 r#"SELECT "hello"."id", "hello"."one1", CAST("hello"."two" AS integer), "hello"."three3" FROM "hello""#,
1132 );
1133 assert_eq!(
1134 Update::one(active_model)
1135 .build(DbBackend::Postgres)
1136 .to_string(),
1137 r#"UPDATE "hello" SET "one1" = 1, "two" = 2, "three3" = 3 WHERE "hello"."id" = 1"#,
1138 );
1139 }
1140
1141 assert_it(hello_expanded::ActiveModel {
1142 id: ActiveValue::set(1),
1143 one: ActiveValue::set(1),
1144 two: ActiveValue::set(2),
1145 three: ActiveValue::set(3),
1146 });
1147 assert_it(hello_compact::ActiveModel {
1148 id: ActiveValue::set(1),
1149 one: ActiveValue::set(1),
1150 two: ActiveValue::set(2),
1151 three: ActiveValue::set(3),
1152 });
1153 }
1154
1155 #[test]
1156 #[cfg(feature = "macros")]
1157 fn save_as_1() {
1158 use crate::{ActiveModelTrait, ActiveValue, Update};
1159
1160 mod hello_expanded {
1161 use crate as sea_orm;
1162 use crate::entity::prelude::*;
1163 use crate::sea_query::{Expr, SimpleExpr};
1164
1165 #[derive(Copy, Clone, Default, Debug, DeriveEntity)]
1166 pub struct Entity;
1167
1168 impl EntityName for Entity {
1169 fn table_name(&self) -> &str {
1170 "hello"
1171 }
1172 }
1173
1174 #[derive(Clone, Debug, PartialEq, Eq, DeriveModel, DeriveActiveModel)]
1175 pub struct Model {
1176 pub id: i32,
1177 #[sea_orm(enum_name = "One1")]
1178 pub one: i32,
1179 pub two: i32,
1180 #[sea_orm(enum_name = "Three3")]
1181 pub three: i32,
1182 }
1183
1184 #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
1185 pub enum Column {
1186 Id,
1187 One1,
1188 Two,
1189 Three3,
1190 }
1191
1192 impl ColumnTrait for Column {
1193 type EntityName = Entity;
1194
1195 fn def(&self) -> ColumnDef {
1196 match self {
1197 Column::Id => ColumnType::Integer.def(),
1198 Column::One1 => ColumnType::Integer.def(),
1199 Column::Two => ColumnType::Integer.def(),
1200 Column::Three3 => ColumnType::Integer.def(),
1201 }
1202 }
1203
1204 fn save_as(&self, val: Expr) -> SimpleExpr {
1205 match self {
1206 Self::Two => val.cast_as("text"),
1207 _ => self.save_enum_as(val),
1208 }
1209 }
1210 }
1211
1212 #[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
1213 pub enum PrimaryKey {
1214 Id,
1215 }
1216
1217 impl PrimaryKeyTrait for PrimaryKey {
1218 type ValueType = i32;
1219
1220 fn auto_increment() -> bool {
1221 true
1222 }
1223 }
1224
1225 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1226 pub enum Relation {}
1227
1228 impl ActiveModelBehavior for ActiveModel {}
1229 }
1230
1231 #[allow(clippy::enum_variant_names)]
1232 mod hello_compact {
1233 use crate as sea_orm;
1234 use crate::entity::prelude::*;
1235
1236 #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
1237 #[sea_orm(table_name = "hello")]
1238 pub struct Model {
1239 #[sea_orm(primary_key)]
1240 pub id: i32,
1241 #[sea_orm(enum_name = "One1")]
1242 pub one: i32,
1243 #[sea_orm(save_as = "text")]
1244 pub two: i32,
1245 #[sea_orm(enum_name = "Three3")]
1246 pub three: i32,
1247 }
1248
1249 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1250 pub enum Relation {}
1251
1252 impl ActiveModelBehavior for ActiveModel {}
1253 }
1254
1255 fn assert_it<E, A>(active_model: A)
1256 where
1257 E: EntityTrait,
1258 A: ActiveModelTrait<Entity = E>,
1259 {
1260 assert_eq!(
1261 E::find().build(DbBackend::Postgres).to_string(),
1262 r#"SELECT "hello"."id", "hello"."one1", "hello"."two", "hello"."three3" FROM "hello""#,
1263 );
1264 assert_eq!(
1265 Update::one(active_model)
1266 .build(DbBackend::Postgres)
1267 .to_string(),
1268 r#"UPDATE "hello" SET "one1" = 1, "two" = CAST(2 AS text), "three3" = 3 WHERE "hello"."id" = 1"#,
1269 );
1270 }
1271
1272 assert_it(hello_expanded::ActiveModel {
1273 id: ActiveValue::set(1),
1274 one: ActiveValue::set(1),
1275 two: ActiveValue::set(2),
1276 three: ActiveValue::set(3),
1277 });
1278 assert_it(hello_compact::ActiveModel {
1279 id: ActiveValue::set(1),
1280 one: ActiveValue::set(1),
1281 two: ActiveValue::set(2),
1282 three: ActiveValue::set(3),
1283 });
1284 }
1285
1286 #[test]
1287 #[cfg(feature = "macros")]
1288 fn select_as_and_value_1() {
1289 use crate::{ActiveModelTrait, ActiveValue, Update};
1290
1291 mod hello_expanded {
1292 use crate as sea_orm;
1293 use crate::entity::prelude::*;
1294 use crate::sea_query::{Expr, SimpleExpr};
1295
1296 #[derive(Copy, Clone, Default, Debug, DeriveEntity)]
1297 pub struct Entity;
1298
1299 impl EntityName for Entity {
1300 fn table_name(&self) -> &str {
1301 "hello"
1302 }
1303 }
1304
1305 #[derive(Clone, Debug, PartialEq, Eq, DeriveModel, DeriveActiveModel)]
1306 pub struct Model {
1307 pub id: i32,
1308 #[sea_orm(enum_name = "One1")]
1309 pub one: i32,
1310 pub two: i32,
1311 #[sea_orm(enum_name = "Three3")]
1312 pub three: i32,
1313 }
1314
1315 #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
1316 pub enum Column {
1317 Id,
1318 One1,
1319 Two,
1320 Three3,
1321 }
1322
1323 impl ColumnTrait for Column {
1324 type EntityName = Entity;
1325
1326 fn def(&self) -> ColumnDef {
1327 match self {
1328 Column::Id => ColumnType::Integer.def(),
1329 Column::One1 => ColumnType::Integer.def(),
1330 Column::Two => ColumnType::Integer.def(),
1331 Column::Three3 => ColumnType::Integer.def(),
1332 }
1333 }
1334
1335 fn select_as(&self, expr: Expr) -> SimpleExpr {
1336 match self {
1337 Self::Two => expr.cast_as("integer"),
1338 _ => self.select_enum_as(expr),
1339 }
1340 }
1341
1342 fn save_as(&self, val: Expr) -> SimpleExpr {
1343 match self {
1344 Self::Two => val.cast_as("text"),
1345 _ => self.save_enum_as(val),
1346 }
1347 }
1348 }
1349
1350 #[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
1351 pub enum PrimaryKey {
1352 Id,
1353 }
1354
1355 impl PrimaryKeyTrait for PrimaryKey {
1356 type ValueType = i32;
1357
1358 fn auto_increment() -> bool {
1359 true
1360 }
1361 }
1362
1363 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1364 pub enum Relation {}
1365
1366 impl ActiveModelBehavior for ActiveModel {}
1367 }
1368
1369 #[allow(clippy::enum_variant_names)]
1370 mod hello_compact {
1371 use crate as sea_orm;
1372 use crate::entity::prelude::*;
1373
1374 #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
1375 #[sea_orm(table_name = "hello")]
1376 pub struct Model {
1377 #[sea_orm(primary_key)]
1378 pub id: i32,
1379 #[sea_orm(enum_name = "One1")]
1380 pub one: i32,
1381 #[sea_orm(select_as = "integer", save_as = "text")]
1382 pub two: i32,
1383 #[sea_orm(enum_name = "Three3")]
1384 pub three: i32,
1385 }
1386
1387 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
1388 pub enum Relation {}
1389
1390 impl ActiveModelBehavior for ActiveModel {}
1391 }
1392
1393 fn assert_it<E, A>(active_model: A)
1394 where
1395 E: EntityTrait,
1396 A: ActiveModelTrait<Entity = E>,
1397 {
1398 assert_eq!(
1399 E::find().build(DbBackend::Postgres).to_string(),
1400 r#"SELECT "hello"."id", "hello"."one1", CAST("hello"."two" AS integer), "hello"."three3" FROM "hello""#,
1401 );
1402 assert_eq!(
1403 Update::one(active_model)
1404 .build(DbBackend::Postgres)
1405 .to_string(),
1406 r#"UPDATE "hello" SET "one1" = 1, "two" = CAST(2 AS text), "three3" = 3 WHERE "hello"."id" = 1"#,
1407 );
1408 }
1409
1410 assert_it(hello_expanded::ActiveModel {
1411 id: ActiveValue::set(1),
1412 one: ActiveValue::set(1),
1413 two: ActiveValue::set(2),
1414 three: ActiveValue::set(3),
1415 });
1416 assert_it(hello_compact::ActiveModel {
1417 id: ActiveValue::set(1),
1418 one: ActiveValue::set(1),
1419 two: ActiveValue::set(2),
1420 three: ActiveValue::set(3),
1421 });
1422 }
1423}