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