Skip to main content

drizzle_types/postgres/ddl/
sequence.rs

1//! `PostgreSQL` Sequence DDL types
2//!
3//! See: <https://github.com/drizzle-team/drizzle-orm/blob/beta/drizzle-kit/src/dialects/postgres/ddl.ts>
4
5use crate::alloc_prelude::*;
6
7#[cfg(feature = "serde")]
8use crate::serde_helpers::{cow_from_string, cow_option_from_string};
9
10// =============================================================================
11// Const-friendly Definition Type
12// =============================================================================
13
14/// Const-friendly sequence definition for compile-time schema definitions.
15#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
16pub struct SequenceDef {
17    /// Schema name
18    pub schema: &'static str,
19    /// Sequence name
20    pub name: &'static str,
21    /// Increment value (as string for const compatibility)
22    pub increment_by: Option<&'static str>,
23    /// Minimum value (as string)
24    pub min_value: Option<&'static str>,
25    /// Maximum value (as string)
26    pub max_value: Option<&'static str>,
27    /// Start value (as string)
28    pub start_with: Option<&'static str>,
29    /// Cache size
30    pub cache_size: Option<i32>,
31    /// Cycle flag
32    pub cycle: Option<bool>,
33}
34
35impl SequenceDef {
36    /// Create a new sequence definition
37    #[must_use]
38    pub const fn new(schema: &'static str, name: &'static str) -> Self {
39        Self {
40            schema,
41            name,
42            increment_by: None,
43            min_value: None,
44            max_value: None,
45            start_with: None,
46            cache_size: None,
47            cycle: None,
48        }
49    }
50
51    /// Set increment value
52    #[must_use]
53    pub const fn increment_by(self, value: &'static str) -> Self {
54        Self {
55            increment_by: Some(value),
56            ..self
57        }
58    }
59
60    /// Set minimum value
61    #[must_use]
62    pub const fn min_value(self, value: &'static str) -> Self {
63        Self {
64            min_value: Some(value),
65            ..self
66        }
67    }
68
69    /// Set maximum value
70    #[must_use]
71    pub const fn max_value(self, value: &'static str) -> Self {
72        Self {
73            max_value: Some(value),
74            ..self
75        }
76    }
77
78    /// Set start value
79    #[must_use]
80    pub const fn start_with(self, value: &'static str) -> Self {
81        Self {
82            start_with: Some(value),
83            ..self
84        }
85    }
86
87    /// Set cache size
88    #[must_use]
89    pub const fn cache_size(self, value: i32) -> Self {
90        Self {
91            cache_size: Some(value),
92            ..self
93        }
94    }
95
96    /// Set cycle flag
97    #[must_use]
98    pub const fn cycle(self, value: bool) -> Self {
99        Self {
100            cycle: Some(value),
101            ..self
102        }
103    }
104
105    /// Convert to runtime [`Sequence`] type
106    #[must_use]
107    pub const fn into_sequence(self) -> Sequence {
108        Sequence {
109            schema: Cow::Borrowed(self.schema),
110            name: Cow::Borrowed(self.name),
111            increment_by: match self.increment_by {
112                Some(s) => Some(Cow::Borrowed(s)),
113                None => None,
114            },
115            min_value: match self.min_value {
116                Some(s) => Some(Cow::Borrowed(s)),
117                None => None,
118            },
119            max_value: match self.max_value {
120                Some(s) => Some(Cow::Borrowed(s)),
121                None => None,
122            },
123            start_with: match self.start_with {
124                Some(s) => Some(Cow::Borrowed(s)),
125                None => None,
126            },
127            cache_size: self.cache_size,
128            cycle: self.cycle,
129        }
130    }
131}
132
133impl Default for SequenceDef {
134    fn default() -> Self {
135        Self::new("public", "")
136    }
137}
138
139// =============================================================================
140// Runtime Type for Serde
141// =============================================================================
142
143/// Runtime sequence entity for serde serialization.
144#[derive(Clone, Debug, PartialEq, Eq)]
145#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
146#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
147pub struct Sequence {
148    /// Schema name
149    #[cfg_attr(feature = "serde", serde(deserialize_with = "cow_from_string"))]
150    pub schema: Cow<'static, str>,
151
152    /// Sequence name
153    #[cfg_attr(feature = "serde", serde(deserialize_with = "cow_from_string"))]
154    pub name: Cow<'static, str>,
155
156    /// Increment value
157    #[cfg_attr(
158        feature = "serde",
159        serde(
160            default,
161            skip_serializing_if = "Option::is_none",
162            deserialize_with = "cow_option_from_string"
163        )
164    )]
165    pub increment_by: Option<Cow<'static, str>>,
166
167    /// Minimum value
168    #[cfg_attr(
169        feature = "serde",
170        serde(
171            default,
172            skip_serializing_if = "Option::is_none",
173            deserialize_with = "cow_option_from_string"
174        )
175    )]
176    pub min_value: Option<Cow<'static, str>>,
177
178    /// Maximum value
179    #[cfg_attr(
180        feature = "serde",
181        serde(
182            default,
183            skip_serializing_if = "Option::is_none",
184            deserialize_with = "cow_option_from_string"
185        )
186    )]
187    pub max_value: Option<Cow<'static, str>>,
188
189    /// Start value
190    #[cfg_attr(
191        feature = "serde",
192        serde(
193            default,
194            skip_serializing_if = "Option::is_none",
195            deserialize_with = "cow_option_from_string"
196        )
197    )]
198    pub start_with: Option<Cow<'static, str>>,
199
200    /// Cache size
201    #[cfg_attr(
202        feature = "serde",
203        serde(default, skip_serializing_if = "Option::is_none")
204    )]
205    pub cache_size: Option<i32>,
206
207    /// Cycle flag
208    #[cfg_attr(
209        feature = "serde",
210        serde(default, skip_serializing_if = "Option::is_none")
211    )]
212    pub cycle: Option<bool>,
213}
214
215impl Sequence {
216    /// Create a new sequence (runtime)
217    #[must_use]
218    pub fn new(schema: impl Into<Cow<'static, str>>, name: impl Into<Cow<'static, str>>) -> Self {
219        Self {
220            schema: schema.into(),
221            name: name.into(),
222            increment_by: None,
223            min_value: None,
224            max_value: None,
225            start_with: None,
226            cache_size: None,
227            cycle: None,
228        }
229    }
230
231    /// Get the schema name
232    #[inline]
233    #[must_use]
234    pub fn schema(&self) -> &str {
235        &self.schema
236    }
237
238    /// Get the sequence name
239    #[inline]
240    #[must_use]
241    pub fn name(&self) -> &str {
242        &self.name
243    }
244}
245
246impl Default for Sequence {
247    fn default() -> Self {
248        Self::new("public", "")
249    }
250}
251
252impl From<SequenceDef> for Sequence {
253    fn from(def: SequenceDef) -> Self {
254        def.into_sequence()
255    }
256}
257
258#[cfg(test)]
259mod tests {
260    use super::*;
261
262    #[test]
263    fn test_const_sequence_def() {
264        const SEQ: SequenceDef = SequenceDef::new("public", "users_id_seq")
265            .increment_by("1")
266            .start_with("1")
267            .cycle(true);
268
269        assert_eq!(SEQ.schema, "public");
270        assert_eq!(SEQ.name, "users_id_seq");
271        assert_eq!(SEQ.increment_by, Some("1"));
272        assert_eq!(SEQ.cycle, Some(true));
273    }
274
275    #[test]
276    fn test_sequence_def_to_sequence() {
277        const DEF: SequenceDef = SequenceDef::new("public", "seq").increment_by("1");
278        let seq = DEF.into_sequence();
279        assert_eq!(seq.schema(), "public");
280        assert_eq!(seq.name(), "seq");
281        assert_eq!(seq.increment_by.as_ref().map(|s| s.as_ref()), Some("1"));
282    }
283
284    #[test]
285    fn test_sequence_with_cache() {
286        const SEQ: SequenceDef = SequenceDef::new("public", "seq").cache_size(100);
287        let seq = SEQ.into_sequence();
288        assert_eq!(seq.cache_size, Some(100));
289    }
290}