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, Hash)]
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    /// Iterate components of Identity
30    pub fn iter(&self) -> BorrowedIdentityIter<'_> {
31        BorrowedIdentityIter {
32            identity: self,
33            index: 0,
34        }
35    }
36}
37
38impl IntoIterator for Identity {
39    type Item = DynIden;
40    type IntoIter = OwnedIdentityIter;
41
42    fn into_iter(self) -> Self::IntoIter {
43        OwnedIdentityIter {
44            identity: self,
45            index: 0,
46        }
47    }
48}
49
50impl Iden for Identity {
51    fn quoted(&self) -> Cow<'static, str> {
52        match self {
53            Identity::Unary(iden) => iden.inner(),
54            Identity::Binary(iden1, iden2) => Cow::Owned(format!("{iden1}{iden2}")),
55            Identity::Ternary(iden1, iden2, iden3) => Cow::Owned(format!("{iden1}{iden2}{iden3}")),
56            Identity::Many(vec) => {
57                let mut s = String::new();
58                for iden in vec.iter() {
59                    write!(&mut s, "{iden}").expect("Infallible");
60                }
61                Cow::Owned(s)
62            }
63        }
64    }
65
66    fn to_string(&self) -> String {
67        match self.quoted() {
68            Cow::Borrowed(s) => s.to_owned(),
69            Cow::Owned(s) => s,
70        }
71    }
72
73    fn unquoted(&self) -> &str {
74        panic!("Should not call this")
75    }
76}
77
78/// Iterator for [`Identity`]
79#[derive(Debug)]
80pub struct BorrowedIdentityIter<'a> {
81    identity: &'a Identity,
82    index: usize,
83}
84
85/// Iterator for [`Identity`]
86#[derive(Debug)]
87pub struct OwnedIdentityIter {
88    identity: Identity,
89    index: usize,
90}
91
92impl<'a> Iterator for BorrowedIdentityIter<'a> {
93    type Item = &'a DynIden;
94
95    fn next(&mut self) -> Option<Self::Item> {
96        let result = match self.identity {
97            Identity::Unary(iden1) => {
98                if self.index == 0 {
99                    Some(iden1)
100                } else {
101                    None
102                }
103            }
104            Identity::Binary(iden1, iden2) => match self.index {
105                0 => Some(iden1),
106                1 => Some(iden2),
107                _ => None,
108            },
109            Identity::Ternary(iden1, iden2, iden3) => match self.index {
110                0 => Some(iden1),
111                1 => Some(iden2),
112                2 => Some(iden3),
113                _ => None,
114            },
115            Identity::Many(vec) => vec.get(self.index),
116        };
117        self.index += 1;
118        result
119    }
120}
121
122impl Iterator for OwnedIdentityIter {
123    type Item = DynIden;
124
125    fn next(&mut self) -> Option<Self::Item> {
126        let result = match &self.identity {
127            Identity::Unary(iden1) => {
128                if self.index == 0 {
129                    Some(iden1.clone())
130                } else {
131                    None
132                }
133            }
134            Identity::Binary(iden1, iden2) => match self.index {
135                0 => Some(iden1.clone()),
136                1 => Some(iden2.clone()),
137                _ => None,
138            },
139            Identity::Ternary(iden1, iden2, iden3) => match self.index {
140                0 => Some(iden1.clone()),
141                1 => Some(iden2.clone()),
142                2 => Some(iden3.clone()),
143                _ => None,
144            },
145            Identity::Many(vec) => vec.get(self.index).cloned(),
146        };
147        self.index += 1;
148        result
149    }
150}
151
152/// Performs a conversion into an [Identity]
153pub trait IntoIdentity {
154    /// Method to perform the conversion
155    fn into_identity(self) -> Identity;
156}
157
158/// Check the [Identity] of an Entity
159pub trait IdentityOf<E>
160where
161    E: EntityTrait,
162{
163    /// Method to call to perform this check
164    fn identity_of(self) -> Identity;
165}
166
167impl IntoIdentity for Identity {
168    fn into_identity(self) -> Identity {
169        self
170    }
171}
172
173impl IntoIdentity for String {
174    fn into_identity(self) -> Identity {
175        self.as_str().into_identity()
176    }
177}
178
179impl IntoIdentity for &str {
180    fn into_identity(self) -> Identity {
181        Identity::Unary(SeaRc::new(Alias::new(self)))
182    }
183}
184
185impl<T> IntoIdentity for T
186where
187    T: IdenStatic,
188{
189    fn into_identity(self) -> Identity {
190        Identity::Unary(self.into_iden())
191    }
192}
193
194impl<T, C> IntoIdentity for (T, C)
195where
196    T: IdenStatic,
197    C: IdenStatic,
198{
199    fn into_identity(self) -> Identity {
200        Identity::Binary(self.0.into_iden(), self.1.into_iden())
201    }
202}
203
204impl<T, C, R> IntoIdentity for (T, C, R)
205where
206    T: IdenStatic,
207    C: IdenStatic,
208    R: IdenStatic,
209{
210    fn into_identity(self) -> Identity {
211        Identity::Ternary(self.0.into_iden(), self.1.into_iden(), self.2.into_iden())
212    }
213}
214
215macro_rules! impl_into_identity {
216    ( $($T:ident : $N:tt),+ $(,)? ) => {
217        impl< $($T),+ > IntoIdentity for ( $($T),+ )
218        where
219            $($T: IdenStatic),+
220        {
221            fn into_identity(self) -> Identity {
222                Identity::Many(vec![
223                    $(self.$N.into_iden()),+
224                ])
225            }
226        }
227    };
228}
229
230#[rustfmt::skip]
231mod impl_into_identity {
232    use super::*;
233
234    impl_into_identity!(T0:0, T1:1, T2:2, T3:3);
235    impl_into_identity!(T0:0, T1:1, T2:2, T3:3, T4:4);
236    impl_into_identity!(T0:0, T1:1, T2:2, T3:3, T4:4, T5:5);
237    impl_into_identity!(T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6);
238    impl_into_identity!(T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6, T7:7);
239    impl_into_identity!(T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6, T7:7, T8:8);
240    impl_into_identity!(T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6, T7:7, T8:8, T9:9);
241    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);
242    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);
243}
244
245impl<E, C> IdentityOf<E> for C
246where
247    E: EntityTrait<Column = C>,
248    C: ColumnTrait,
249{
250    fn identity_of(self) -> Identity {
251        self.into_identity()
252    }
253}
254
255macro_rules! impl_identity_of {
256    ( $($T:ident),+ $(,)? ) => {
257        impl<E, C> IdentityOf<E> for ( $($T),+ )
258        where
259            E: EntityTrait<Column = C>,
260            C: ColumnTrait,
261        {
262            fn identity_of(self) -> Identity {
263                self.into_identity()
264            }
265        }
266    };
267}
268
269#[rustfmt::skip]
270mod impl_identity_of {
271    use super::*;
272
273    impl_identity_of!(C, C);
274    impl_identity_of!(C, C, C);
275    impl_identity_of!(C, C, C, C);
276    impl_identity_of!(C, C, C, C, C);
277    impl_identity_of!(C, C, C, C, C, C);
278    impl_identity_of!(C, C, C, C, C, C, C);
279    impl_identity_of!(C, C, C, C, C, C, C, C);
280    impl_identity_of!(C, C, C, C, C, C, C, C, C);
281    impl_identity_of!(C, C, C, C, C, C, C, C, C, C);
282    impl_identity_of!(C, C, C, C, C, C, C, C, C, C, C);
283    impl_identity_of!(C, C, C, C, C, C, C, C, C, C, C, C);
284}