1mod primitive;
2pub use primitive::{FieldPrimitive, SerializeFormat};
3
4use super::{
5 AutoStrategy, BelongsTo, Constraint, Embedded, HasMany, HasOne, Model, ModelId, Schema,
6 VariantId,
7};
8use crate::{driver, stmt, Result};
9use std::fmt;
10
11#[derive(Debug, Clone)]
12pub struct Field {
13 pub id: FieldId,
15
16 pub name: FieldName,
18
19 pub ty: FieldTy,
21
22 pub nullable: bool,
24
25 pub primary_key: bool,
27
28 pub auto: Option<AutoStrategy>,
30
31 pub constraints: Vec<Constraint>,
33
34 pub variant: Option<VariantId>,
37}
38
39#[derive(Copy, Clone, PartialEq, Eq, Hash)]
40#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
41pub struct FieldId {
42 pub model: ModelId,
43 pub index: usize,
44}
45
46#[derive(Debug, Clone)]
47pub struct FieldName {
48 pub app_name: String,
49 pub storage_name: Option<String>,
50}
51
52impl FieldName {
53 pub fn storage_name(&self) -> &str {
54 self.storage_name.as_ref().unwrap_or(&self.app_name)
55 }
56}
57
58#[derive(Clone)]
59pub enum FieldTy {
60 Primitive(FieldPrimitive),
61 Embedded(Embedded),
62 BelongsTo(BelongsTo),
63 HasMany(HasMany),
64 HasOne(HasOne),
65}
66
67impl Field {
68 pub fn id(&self) -> FieldId {
70 self.id
71 }
72
73 pub fn name(&self) -> &FieldName {
75 &self.name
76 }
77
78 pub fn ty(&self) -> &FieldTy {
80 &self.ty
81 }
82
83 pub fn nullable(&self) -> bool {
85 self.nullable
86 }
87
88 pub fn primary_key(&self) -> bool {
90 self.primary_key
91 }
92
93 pub fn auto(&self) -> Option<&AutoStrategy> {
95 self.auto.as_ref()
96 }
97
98 pub fn is_auto_increment(&self) -> bool {
99 self.auto().map(|auto| auto.is_increment()).unwrap_or(false)
100 }
101
102 pub fn is_relation(&self) -> bool {
103 self.ty.is_relation()
104 }
105
106 pub fn full_name(&self, schema: &Schema) -> String {
108 let model = schema.model(self.id.model);
109 format!(
110 "{}::{}",
111 model.name().upper_camel_case(),
112 self.name.app_name
113 )
114 }
115
116 pub fn relation_target_id(&self) -> Option<ModelId> {
118 match &self.ty {
119 FieldTy::BelongsTo(belongs_to) => Some(belongs_to.target),
120 FieldTy::HasMany(has_many) => Some(has_many.target),
121 _ => None,
122 }
123 }
124
125 pub fn relation_target<'a>(&self, schema: &'a Schema) -> Option<&'a Model> {
127 self.relation_target_id().map(|id| schema.model(id))
128 }
129
130 pub fn expr_ty(&self) -> &stmt::Type {
132 match &self.ty {
133 FieldTy::Primitive(primitive) => &primitive.ty,
134 FieldTy::Embedded(embedded) => &embedded.expr_ty,
135 FieldTy::BelongsTo(belongs_to) => &belongs_to.expr_ty,
136 FieldTy::HasMany(has_many) => &has_many.expr_ty,
137 FieldTy::HasOne(has_one) => &has_one.expr_ty,
138 }
139 }
140
141 pub fn pair(&self) -> Option<FieldId> {
142 match &self.ty {
143 FieldTy::Primitive(_) => None,
144 FieldTy::Embedded(_) => None,
145 FieldTy::BelongsTo(belongs_to) => belongs_to.pair,
146 FieldTy::HasMany(has_many) => Some(has_many.pair),
147 FieldTy::HasOne(has_one) => Some(has_one.pair),
148 }
149 }
150
151 pub(crate) fn verify(&self, db: &driver::Capability) -> Result<()> {
152 if let FieldTy::Primitive(primitive) = &self.ty {
153 if let Some(storage_ty) = &primitive.storage_ty {
154 storage_ty.verify(db)?;
155 }
156 }
157
158 Ok(())
159 }
160}
161
162impl FieldTy {
163 pub fn is_primitive(&self) -> bool {
164 matches!(self, Self::Primitive(..))
165 }
166
167 pub fn as_primitive(&self) -> Option<&FieldPrimitive> {
168 match self {
169 Self::Primitive(primitive) => Some(primitive),
170 _ => None,
171 }
172 }
173
174 #[track_caller]
175 pub fn expect_primitive(&self) -> &FieldPrimitive {
176 match self {
177 Self::Primitive(simple) => simple,
178 _ => panic!("expected simple field, but was {self:?}"),
179 }
180 }
181
182 #[track_caller]
183 pub fn expect_primitive_mut(&mut self) -> &mut FieldPrimitive {
184 match self {
185 Self::Primitive(simple) => simple,
186 _ => panic!("expected simple field, but was {self:?}"),
187 }
188 }
189
190 pub fn is_embedded(&self) -> bool {
191 matches!(self, Self::Embedded(..))
192 }
193
194 pub fn as_embedded(&self) -> Option<&Embedded> {
195 match self {
196 Self::Embedded(embedded) => Some(embedded),
197 _ => None,
198 }
199 }
200
201 #[track_caller]
202 pub fn expect_embedded(&self) -> &Embedded {
203 match self {
204 Self::Embedded(embedded) => embedded,
205 _ => panic!("expected embedded field, but was {self:?}"),
206 }
207 }
208
209 #[track_caller]
210 pub fn expect_embedded_mut(&mut self) -> &mut Embedded {
211 match self {
212 Self::Embedded(embedded) => embedded,
213 _ => panic!("expected embedded field, but was {self:?}"),
214 }
215 }
216
217 pub fn is_relation(&self) -> bool {
218 matches!(
219 self,
220 Self::BelongsTo(..) | Self::HasMany(..) | Self::HasOne(..)
221 )
222 }
223
224 pub fn is_has_n(&self) -> bool {
225 matches!(self, Self::HasMany(..) | Self::HasOne(..))
226 }
227
228 pub fn is_has_many(&self) -> bool {
229 matches!(self, Self::HasMany(..))
230 }
231
232 pub fn as_has_many(&self) -> Option<&HasMany> {
233 match self {
234 Self::HasMany(has_many) => Some(has_many),
235 _ => None,
236 }
237 }
238
239 #[track_caller]
240 pub fn expect_has_many(&self) -> &HasMany {
241 match self {
242 Self::HasMany(has_many) => has_many,
243 _ => panic!("expected field to be `HasMany`, but was {self:?}"),
244 }
245 }
246
247 #[track_caller]
248 pub fn expect_has_many_mut(&mut self) -> &mut HasMany {
249 match self {
250 Self::HasMany(has_many) => has_many,
251 _ => panic!("expected field to be `HasMany`, but was {self:?}"),
252 }
253 }
254
255 pub fn as_has_one(&self) -> Option<&HasOne> {
256 match self {
257 Self::HasOne(has_one) => Some(has_one),
258 _ => None,
259 }
260 }
261
262 pub fn is_has_one(&self) -> bool {
263 matches!(self, Self::HasOne(..))
264 }
265
266 #[track_caller]
267 pub fn expect_has_one(&self) -> &HasOne {
268 match self {
269 Self::HasOne(has_one) => has_one,
270 _ => panic!("expected field to be `HasOne`, but it was {self:?}"),
271 }
272 }
273
274 #[track_caller]
275 pub fn expect_has_one_mut(&mut self) -> &mut HasOne {
276 match self {
277 Self::HasOne(has_one) => has_one,
278 _ => panic!("expected field to be `HasOne`, but it was {self:?}"),
279 }
280 }
281
282 pub fn is_belongs_to(&self) -> bool {
283 matches!(self, Self::BelongsTo(..))
284 }
285
286 pub fn as_belongs_to(&self) -> Option<&BelongsTo> {
287 match self {
288 Self::BelongsTo(belongs_to) => Some(belongs_to),
289 _ => None,
290 }
291 }
292
293 #[track_caller]
294 pub fn expect_belongs_to(&self) -> &BelongsTo {
295 match self {
296 Self::BelongsTo(belongs_to) => belongs_to,
297 _ => panic!("expected field to be `BelongsTo`, but was {self:?}"),
298 }
299 }
300
301 #[track_caller]
302 pub fn expect_belongs_to_mut(&mut self) -> &mut BelongsTo {
303 match self {
304 Self::BelongsTo(belongs_to) => belongs_to,
305 _ => panic!("expected field to be `BelongsTo`, but was {self:?}"),
306 }
307 }
308}
309
310impl fmt::Debug for FieldTy {
311 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
312 match self {
313 Self::Primitive(ty) => ty.fmt(fmt),
314 Self::Embedded(ty) => ty.fmt(fmt),
315 Self::BelongsTo(ty) => ty.fmt(fmt),
316 Self::HasMany(ty) => ty.fmt(fmt),
317 Self::HasOne(ty) => ty.fmt(fmt),
318 }
319 }
320}
321
322impl FieldId {
323 pub(crate) fn placeholder() -> Self {
324 Self {
325 model: ModelId::placeholder(),
326 index: usize::MAX,
327 }
328 }
329}
330
331impl From<&Self> for FieldId {
332 fn from(val: &Self) -> Self {
333 *val
334 }
335}
336
337impl From<&Field> for FieldId {
338 fn from(val: &Field) -> Self {
339 val.id
340 }
341}
342
343impl From<FieldId> for usize {
344 fn from(val: FieldId) -> Self {
345 val.index
346 }
347}
348
349impl fmt::Debug for FieldId {
350 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
351 write!(fmt, "FieldId({}/{})", self.model.0, self.index)
352 }
353}