1use crate::{ColumnTrait, EntityTrait, IdenStatic};
2use sea_query::{Alias, DynIden, Iden, IntoIden, SeaRc};
3use std::{borrow::Cow, fmt::Write};
4
5#[derive(Debug, Clone)]
7pub enum Identity {
8 Unary(DynIden),
10 Binary(DynIden, DynIden),
12 Ternary(DynIden, DynIden, DynIden),
14 Many(Vec<DynIden>),
16}
17
18impl Identity {
19 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
72pub trait IntoIdentity {
74 fn into_identity(self) -> Identity;
76}
77
78pub trait IdentityOf<E>
80where
81 E: EntityTrait,
82{
83 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}