sea_orm/entity/
primary_key.rs

1use super::{ColumnTrait, IdenStatic, Iterable};
2use crate::{TryFromU64, TryGetableMany};
3use sea_query::{FromValueTuple, IntoValueTuple};
4use std::fmt::Debug;
5
6/// A Trait for to be used to define a Primary Key.
7///
8/// A primary key can be derived manually
9///
10/// ### Example
11/// ```text
12/// use sea_orm::entity::prelude::*;
13///
14/// #[derive(Copy, Clone, Debug, EnumIter)]
15/// pub enum PrimaryKey {
16///     Id,
17/// }
18/// impl PrimaryKeyTrait for PrimaryKey {
19///     type ValueType = i32;
20///
21///     fn auto_increment() -> bool {
22///         true
23///     }
24/// }
25/// ```
26///
27/// Alternatively, use derive macros to automatically implement the trait for a Primary Key
28///
29/// ### Example
30/// ```text
31/// use sea_orm::entity::prelude::*;
32///
33/// #[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
34/// pub enum PrimaryKey {
35///     Id,
36/// }
37/// ```
38/// See module level docs [crate::entity] for a full example
39pub trait PrimaryKeyTrait: IdenStatic + Iterable {
40    #[allow(missing_docs)]
41    type ValueType: Sized
42        + Debug
43        + PartialEq
44        + IntoValueTuple
45        + FromValueTuple
46        + TryGetableMany
47        + TryFromU64
48        + PrimaryKeyArity;
49
50    /// Method to call to perform `AUTOINCREMENT` operation on a Primary Key
51    fn auto_increment() -> bool;
52}
53
54/// Trait to map a Primary Key to a column
55pub trait PrimaryKeyToColumn {
56    #[allow(missing_docs)]
57    type Column: ColumnTrait;
58
59    /// Method to map a primary key to a column in an Entity
60    fn into_column(self) -> Self::Column;
61
62    /// Method to map a primary key from a column in an Entity
63    fn from_column(col: Self::Column) -> Option<Self>
64    where
65        Self: Sized;
66}
67
68/// How many columns this Primary Key comprises
69pub trait PrimaryKeyArity {
70    /// Arity of the Primary Key
71    const ARITY: usize;
72}
73
74impl<V> PrimaryKeyArity for V
75where
76    V: crate::TryGetable,
77{
78    const ARITY: usize = 1;
79}
80
81macro_rules! impl_pk_arity {
82    ($len:expr, $($tuple_arg:ident),*) => {
83        impl<$($tuple_arg: crate::TryGetableMany,)*> PrimaryKeyArity for ($($tuple_arg,)*) {
84            const ARITY: usize = $len;
85        }
86    }
87}
88
89impl_pk_arity!(1, T1);
90impl_pk_arity!(2, T1, T2);
91impl_pk_arity!(3, T1, T2, T3);
92impl_pk_arity!(4, T1, T2, T3, T4);
93impl_pk_arity!(5, T1, T2, T3, T4, T5);
94impl_pk_arity!(6, T1, T2, T3, T4, T5, T6);
95impl_pk_arity!(7, T1, T2, T3, T4, T5, T6, T7);
96impl_pk_arity!(8, T1, T2, T3, T4, T5, T6, T7, T8);
97impl_pk_arity!(9, T1, T2, T3, T4, T5, T6, T7, T8, T9);
98impl_pk_arity!(10, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
99impl_pk_arity!(11, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
100impl_pk_arity!(12, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);
101
102#[cfg(test)]
103mod tests {
104    use crate::{EntityTrait, Identity};
105
106    #[test]
107    #[cfg(feature = "macros")]
108    fn test_composite_primary_key() {
109        mod primary_key_of_1 {
110            use crate as sea_orm;
111            use crate::entity::prelude::*;
112
113            #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
114            #[sea_orm(table_name = "primary_key_of_1")]
115            pub struct Model {
116                #[sea_orm(primary_key)]
117                pub id: i32,
118                pub owner: String,
119                pub name: String,
120                pub description: String,
121            }
122
123            #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
124            pub enum Relation {}
125
126            impl ActiveModelBehavior for ActiveModel {}
127        }
128
129        mod primary_key_of_2 {
130            use crate as sea_orm;
131            use crate::entity::prelude::*;
132
133            #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
134            #[sea_orm(table_name = "primary_key_of_2")]
135            pub struct Model {
136                #[sea_orm(primary_key, auto_increment = false)]
137                pub id_1: i32,
138                #[sea_orm(primary_key, auto_increment = false)]
139                pub id_2: String,
140                pub owner: String,
141                pub name: String,
142                pub description: String,
143            }
144
145            #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
146            pub enum Relation {}
147
148            impl ActiveModelBehavior for ActiveModel {}
149        }
150
151        mod primary_key_of_3 {
152            use crate as sea_orm;
153            use crate::entity::prelude::*;
154
155            #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
156            #[sea_orm(table_name = "primary_key_of_3")]
157            pub struct Model {
158                #[sea_orm(primary_key, auto_increment = false)]
159                pub id_1: i32,
160                #[sea_orm(primary_key, auto_increment = false)]
161                pub id_2: String,
162                #[sea_orm(primary_key, auto_increment = false)]
163                pub id_3: Uuid,
164                pub owner: String,
165                pub name: String,
166                pub description: String,
167            }
168
169            #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
170            pub enum Relation {}
171
172            impl ActiveModelBehavior for ActiveModel {}
173        }
174
175        mod primary_key_of_4 {
176            use crate as sea_orm;
177            use crate::entity::prelude::*;
178
179            #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
180            #[sea_orm(table_name = "primary_key_of_4")]
181            pub struct Model {
182                #[sea_orm(primary_key, auto_increment = false)]
183                pub id_1: TimeDateTimeWithTimeZone,
184                #[sea_orm(primary_key, auto_increment = false)]
185                pub id_2: Uuid,
186                #[sea_orm(primary_key, auto_increment = false)]
187                pub id_3: Json,
188                #[sea_orm(primary_key, auto_increment = false)]
189                pub id_4: Decimal,
190                pub owner: String,
191                pub name: String,
192                pub description: String,
193            }
194
195            #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
196            pub enum Relation {}
197
198            impl ActiveModelBehavior for ActiveModel {}
199        }
200
201        mod primary_key_of_11 {
202            use crate as sea_orm;
203            use crate::entity::prelude::*;
204
205            #[derive(Clone, Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)]
206            #[sea_orm(
207                rs_type = "String",
208                db_type = "String(StringLen::N(1))",
209                enum_name = "category"
210            )]
211            pub enum DeriveCategory {
212                #[sea_orm(string_value = "B")]
213                Big,
214                #[sea_orm(string_value = "S")]
215                Small,
216            }
217
218            #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
219            #[sea_orm(table_name = "primary_key_of_11")]
220            pub struct Model {
221                #[sea_orm(primary_key, auto_increment = false)]
222                pub id_1: Vec<u8>,
223                #[sea_orm(primary_key, auto_increment = false)]
224                pub id_2: DeriveCategory,
225                #[sea_orm(primary_key, auto_increment = false)]
226                pub id_3: Date,
227                #[sea_orm(primary_key, auto_increment = false)]
228                pub id_4: DateTime,
229                #[sea_orm(primary_key, auto_increment = false)]
230                pub id_5: Time,
231                #[sea_orm(primary_key, auto_increment = false)]
232                pub id_6: TimeTime,
233                #[sea_orm(primary_key, auto_increment = false)]
234                pub id_7: DateTime,
235                #[sea_orm(primary_key, auto_increment = false)]
236                pub id_8: TimeDateTime,
237                #[sea_orm(primary_key, auto_increment = false)]
238                pub id_9: DateTimeLocal,
239                #[sea_orm(primary_key, auto_increment = false)]
240                pub id_10: DateTimeUtc,
241                #[sea_orm(primary_key, auto_increment = false)]
242                pub id_11: DateTimeWithTimeZone,
243                pub owner: String,
244                pub name: String,
245                pub description: String,
246            }
247
248            #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
249            pub enum Relation {}
250
251            impl ActiveModelBehavior for ActiveModel {}
252        }
253
254        mod primary_key_of_12 {
255            use crate as sea_orm;
256            use crate::entity::prelude::*;
257
258            #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
259            #[sea_orm(table_name = "primary_key_of_12")]
260            pub struct Model {
261                #[sea_orm(primary_key, auto_increment = false)]
262                pub id_1: String,
263                #[sea_orm(primary_key, auto_increment = false)]
264                pub id_2: i8,
265                #[sea_orm(primary_key, auto_increment = false)]
266                pub id_3: u8,
267                #[sea_orm(primary_key, auto_increment = false)]
268                pub id_4: i16,
269                #[sea_orm(primary_key, auto_increment = false)]
270                pub id_5: u16,
271                #[sea_orm(primary_key, auto_increment = false)]
272                pub id_6: i32,
273                #[sea_orm(primary_key, auto_increment = false)]
274                pub id_7: u32,
275                #[sea_orm(primary_key, auto_increment = false)]
276                pub id_8: i64,
277                #[sea_orm(primary_key, auto_increment = false)]
278                pub id_9: u64,
279                #[sea_orm(primary_key, auto_increment = false)]
280                pub id_10: f32,
281                #[sea_orm(primary_key, auto_increment = false)]
282                pub id_11: f64,
283                #[sea_orm(primary_key, auto_increment = false)]
284                pub id_12: bool,
285                pub owner: String,
286                pub name: String,
287                pub description: String,
288            }
289
290            #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
291            pub enum Relation {}
292
293            impl ActiveModelBehavior for ActiveModel {}
294        }
295
296        assert_eq!(
297            primary_key_of_3::Entity::primary_key_identity(),
298            Identity::Ternary("id_1".into(), "id_2".into(), "id_3".into())
299        );
300    }
301}