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