sea_orm/entity/
identity.rs

1use crate::{ColumnTrait, EntityTrait, IdenStatic};
2use sea_query::{Alias, DynIden, Iden, IntoIden, SeaRc};
3use std::{borrow::Cow, fmt::Write};
4
5/// List of column identifier
6#[derive(Debug, Clone)]
7pub enum Identity {
8    /// Column identifier consists of 1 column
9    Unary(DynIden),
10    /// Column identifier consists of 2 columns
11    Binary(DynIden, DynIden),
12    /// Column identifier consists of 3 columns
13    Ternary(DynIden, DynIden, DynIden),
14    /// Column identifier consists of more than 3 columns
15    Many(Vec<DynIden>),
16}
17
18impl Identity {
19    /// Get arity for this value
20    pub fn arity(&self) -> usize {
21        match self {
22            Self::Unary(_) => 1,
23            Self::Binary(_, _) => 2,
24            Self::Ternary(_, _, _) => 3,
25            Self::Many(vec) => vec.len(),
26        }
27    }
28}
29
30impl IntoIterator for Identity {
31    type Item = DynIden;
32    type IntoIter = std::vec::IntoIter<Self::Item>;
33
34    fn into_iter(self) -> Self::IntoIter {
35        match self {
36            Identity::Unary(ident1) => vec![ident1].into_iter(),
37            Identity::Binary(ident1, ident2) => vec![ident1, ident2].into_iter(),
38            Identity::Ternary(ident1, ident2, ident3) => vec![ident1, ident2, ident3].into_iter(),
39            Identity::Many(vec) => vec.into_iter(),
40        }
41    }
42}
43
44impl Iden for Identity {
45    fn quoted(&self) -> Cow<'static, str> {
46        match self {
47            Identity::Unary(iden) => iden.inner(),
48            Identity::Binary(iden1, iden2) => Cow::Owned(format!("{iden1}{iden2}")),
49            Identity::Ternary(iden1, iden2, iden3) => Cow::Owned(format!("{iden1}{iden2}{iden3}")),
50            Identity::Many(vec) => {
51                let mut s = String::new();
52                for iden in vec.iter() {
53                    write!(&mut s, "{iden}").expect("Infallible");
54                }
55                Cow::Owned(s)
56            }
57        }
58    }
59
60    fn to_string(&self) -> String {
61        match self.quoted() {
62            Cow::Borrowed(s) => s.to_owned(),
63            Cow::Owned(s) => s,
64        }
65    }
66
67    fn unquoted(&self) -> &str {
68        panic!("Should not call this")
69    }
70}
71
72/// Performs a conversion into an [Identity]
73pub trait IntoIdentity {
74    /// Method to perform the conversion
75    fn into_identity(self) -> Identity;
76}
77
78/// Check the [Identity] of an Entity
79pub trait IdentityOf<E>
80where
81    E: EntityTrait,
82{
83    /// Method to call to perform this check
84    fn identity_of(self) -> Identity;
85}
86
87impl IntoIdentity for Identity {
88    fn into_identity(self) -> Identity {
89        self
90    }
91}
92
93impl IntoIdentity for String {
94    fn into_identity(self) -> Identity {
95        self.as_str().into_identity()
96    }
97}
98
99impl IntoIdentity for &str {
100    fn into_identity(self) -> Identity {
101        Identity::Unary(SeaRc::new(Alias::new(self)))
102    }
103}
104
105impl<T> IntoIdentity for T
106where
107    T: IdenStatic,
108{
109    fn into_identity(self) -> Identity {
110        Identity::Unary(self.into_iden())
111    }
112}
113
114impl<T, C> IntoIdentity for (T, C)
115where
116    T: IdenStatic,
117    C: IdenStatic,
118{
119    fn into_identity(self) -> Identity {
120        Identity::Binary(self.0.into_iden(), self.1.into_iden())
121    }
122}
123
124impl<T, C, R> IntoIdentity for (T, C, R)
125where
126    T: IdenStatic,
127    C: IdenStatic,
128    R: IdenStatic,
129{
130    fn into_identity(self) -> Identity {
131        Identity::Ternary(self.0.into_iden(), self.1.into_iden(), self.2.into_iden())
132    }
133}
134
135macro_rules! impl_into_identity {
136    ( $($T:ident : $N:tt),+ $(,)? ) => {
137        impl< $($T),+ > IntoIdentity for ( $($T),+ )
138        where
139            $($T: IdenStatic),+
140        {
141            fn into_identity(self) -> Identity {
142                Identity::Many(vec![
143                    $(self.$N.into_iden()),+
144                ])
145            }
146        }
147    };
148}
149
150#[rustfmt::skip]
151mod impl_into_identity {
152    use super::*;
153
154    impl_into_identity!(T0:0, T1:1, T2:2, T3:3);
155    impl_into_identity!(T0:0, T1:1, T2:2, T3:3, T4:4);
156    impl_into_identity!(T0:0, T1:1, T2:2, T3:3, T4:4, T5:5);
157    impl_into_identity!(T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6);
158    impl_into_identity!(T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6, T7:7);
159    impl_into_identity!(T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6, T7:7, T8:8);
160    impl_into_identity!(T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6, T7:7, T8:8, T9:9);
161    impl_into_identity!(T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6, T7:7, T8:8, T9:9, T10:10);
162    impl_into_identity!(T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6, T7:7, T8:8, T9:9, T10:10, T11:11);
163}
164
165impl<E, C> IdentityOf<E> for C
166where
167    E: EntityTrait<Column = C>,
168    C: ColumnTrait,
169{
170    fn identity_of(self) -> Identity {
171        self.into_identity()
172    }
173}
174
175macro_rules! impl_identity_of {
176    ( $($T:ident),+ $(,)? ) => {
177        impl<E, C> IdentityOf<E> for ( $($T),+ )
178        where
179            E: EntityTrait<Column = C>,
180            C: ColumnTrait,
181        {
182            fn identity_of(self) -> Identity {
183                self.into_identity()
184            }
185        }
186    };
187}
188
189#[rustfmt::skip]
190mod impl_identity_of {
191    use super::*;
192
193    impl_identity_of!(C, C);
194    impl_identity_of!(C, C, C);
195    impl_identity_of!(C, C, C, C);
196    impl_identity_of!(C, C, C, C, C);
197    impl_identity_of!(C, C, C, C, C, C);
198    impl_identity_of!(C, C, C, C, C, C, C);
199    impl_identity_of!(C, C, C, C, C, C, C, C);
200    impl_identity_of!(C, C, C, C, C, C, C, C, C);
201    impl_identity_of!(C, C, C, C, C, C, C, C, C, C);
202    impl_identity_of!(C, C, C, C, C, C, C, C, C, C, C);
203    impl_identity_of!(C, C, C, C, C, C, C, C, C, C, C, C);
204}