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