good_ormning/sqlite/schema/
field.rs

1use {
2    std::{
3        fmt::{
4            Debug,
5            Display,
6        },
7        rc::Rc,
8        ops::Deref,
9    },
10    crate::{
11        sqlite::{
12            types::{
13                SimpleSimpleType,
14                SimpleType,
15                Type,
16            },
17            query::{
18                expr::{
19                    Expr,
20                },
21            },
22        },
23    },
24    super::table::{
25        Table,
26    },
27};
28
29#[derive(Clone, Debug)]
30pub struct FieldType {
31    pub type_: Type,
32    pub migration_default: Option<Expr>,
33}
34
35impl FieldType {
36    /// Create a field type from the specified value type.
37    pub fn with(t: &Type) -> Self {
38        Self {
39            type_: t.clone(),
40            migration_default: None,
41        }
42    }
43
44    /// Create a field type from the specified value type, and provide a migration fill
45    /// value.
46    pub fn with_migration(t: &Type, def: Option<Expr>) -> Self {
47        if t.opt {
48            panic!("Optional fields can't have defaults.");
49        }
50        Self {
51            type_: t.clone(),
52            migration_default: def,
53        }
54    }
55}
56
57pub struct FieldBuilder {
58    t: SimpleSimpleType,
59    default_: Option<Expr>,
60    opt: bool,
61    custom: Option<String>,
62}
63
64impl FieldBuilder {
65    fn new(t: SimpleSimpleType) -> FieldBuilder {
66        FieldBuilder {
67            t: t,
68            opt: false,
69            default_: None,
70            custom: None,
71        }
72    }
73
74    /// Make the field optional.
75    pub fn opt(mut self) -> FieldBuilder {
76        if self.default_.is_some() {
77            panic!("Optional fields can't have migration fill expressions.");
78        }
79        self.opt = true;
80        self
81    }
82
83    /// Specify an expression to use to populate the new column in existing rows. This
84    /// is must be specified (only) for non-opt fields in a new version of an existing
85    /// table.
86    pub fn migrate_fill(mut self, expr: Expr) -> FieldBuilder {
87        if self.opt {
88            panic!("Optional fields can't have migration fill expressions.");
89        }
90        self.default_ = Some(expr);
91        self
92    }
93
94    /// Use a custom Rust type for this field. This must be the full path to the type,
95    /// like `crate::abcdef::MyType`.
96    pub fn custom(mut self, type_: impl ToString) -> FieldBuilder {
97        self.custom = Some(type_.to_string());
98        self
99    }
100
101    pub fn build(self) -> FieldType {
102        FieldType {
103            type_: Type {
104                type_: SimpleType {
105                    custom: self.custom,
106                    type_: self.t,
107                },
108                opt: self.opt,
109                array: false,
110            },
111            migration_default: self.default_,
112        }
113    }
114}
115
116pub fn field_bool() -> FieldBuilder {
117    FieldBuilder::new(SimpleSimpleType::Bool)
118}
119
120pub fn field_i32() -> FieldBuilder {
121    FieldBuilder::new(SimpleSimpleType::I32)
122}
123
124pub fn field_i64() -> FieldBuilder {
125    FieldBuilder::new(SimpleSimpleType::I64)
126}
127
128pub fn field_u32() -> FieldBuilder {
129    FieldBuilder::new(SimpleSimpleType::U32)
130}
131
132pub fn field_f32() -> FieldBuilder {
133    FieldBuilder::new(SimpleSimpleType::F32)
134}
135
136pub fn field_f64() -> FieldBuilder {
137    FieldBuilder::new(SimpleSimpleType::F64)
138}
139
140pub fn field_str() -> FieldBuilder {
141    FieldBuilder::new(SimpleSimpleType::String)
142}
143
144pub fn field_bytes() -> FieldBuilder {
145    FieldBuilder::new(SimpleSimpleType::Bytes)
146}
147
148#[cfg(feature = "chrono")]
149pub fn field_utctime_s_chrono() -> FieldBuilder {
150    FieldBuilder::new(SimpleSimpleType::UtcTimeSChrono)
151}
152
153#[cfg(feature = "chrono")]
154pub fn field_utctime_ms_chrono() -> FieldBuilder {
155    FieldBuilder::new(SimpleSimpleType::UtcTimeMsChrono)
156}
157
158#[cfg(feature = "chrono")]
159pub fn field_fixed_offset_time_ms_chrono() -> FieldBuilder {
160    FieldBuilder::new(SimpleSimpleType::FixedOffsetTimeMsChrono)
161}
162
163#[cfg(feature = "jiff")]
164pub fn field_utctime_s_jiff() -> FieldBuilder {
165    FieldBuilder::new(SimpleSimpleType::UtcTimeSJiff)
166}
167
168#[cfg(feature = "jiff")]
169pub fn field_utctime_ms_jiff() -> FieldBuilder {
170    FieldBuilder::new(SimpleSimpleType::UtcTimeMsJiff)
171}
172
173#[derive(Clone, Eq, PartialEq, Hash, Debug, PartialOrd, Ord)]
174pub struct SchemaFieldId(pub String);
175
176impl Display for SchemaFieldId {
177    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
178        Display::fmt(&self.0, f)
179    }
180}
181
182#[derive(Debug)]
183pub struct Field_ {
184    pub table: Table,
185    pub schema_id: SchemaFieldId,
186    pub id: String,
187    pub type_: FieldType,
188}
189
190#[derive(Clone, Debug)]
191pub struct Field(pub Rc<Field_>);
192
193impl std::hash::Hash for Field {
194    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
195        self.0.schema_id.hash(state)
196    }
197}
198
199impl PartialEq for Field {
200    fn eq(&self, other: &Self) -> bool {
201        self.table == other.table && self.schema_id == other.schema_id
202    }
203}
204
205impl Eq for Field { }
206
207impl Deref for Field {
208    type Target = Field_;
209
210    fn deref(&self) -> &Self::Target {
211        self.0.as_ref()
212    }
213}
214
215impl Display for Field {
216    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
217        Display::fmt(&format!("{}.{} ({}.{})", self.table.id, self.id, self.table.schema_id.0, self.schema_id.0), f)
218    }
219}