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