vibesql_catalog/
advanced_objects.rs

1//! Advanced SQL:1999 object definitions
2//! Minimal stub implementations for: DOMAIN, SEQUENCE, TYPE, COLLATION, CHARACTER SET, TRANSLATION
3
4/// Domain - User-defined data type with constraints
5#[derive(Debug, Clone, Default)]
6pub struct Domain {
7    pub name: String,
8    // TODO: Add base_type, constraints when implementing full functionality
9}
10
11impl Domain {
12    pub fn new(name: String) -> Self {
13        Domain { name }
14    }
15}
16
17/// Sequence - Auto-incrementing number generator
18#[derive(Debug, Clone)]
19pub struct Sequence {
20    pub name: String,
21    pub start_with: i64, // Original start value (for RESTART without WITH)
22    pub increment_by: i64,
23    pub min_value: Option<i64>,
24    pub max_value: Option<i64>,
25    pub cycle: bool,
26    pub current_value: i64, // Current sequence value
27    pub exhausted: bool,    // true if reached limit with NO CYCLE
28}
29
30impl Sequence {
31    pub fn new(
32        name: String,
33        start_with: Option<i64>,
34        increment_by: i64,
35        min_value: Option<i64>,
36        max_value: Option<i64>,
37        cycle: bool,
38    ) -> Self {
39        let start = start_with.unwrap_or(if increment_by >= 0 { 1 } else { -1 });
40        Sequence {
41            name,
42            start_with: start,
43            increment_by,
44            min_value,
45            max_value,
46            cycle,
47            current_value: start,
48            exhausted: false,
49        }
50    }
51
52    /// Get the next value from the sequence
53    pub fn next_value(&mut self) -> Result<i64, String> {
54        if self.exhausted {
55            return Err(format!("Sequence {} is exhausted", self.name));
56        }
57
58        let value = self.current_value;
59
60        // Advance the sequence
61        let next = value
62            .checked_add(self.increment_by)
63            .ok_or_else(|| format!("Sequence {} overflow", self.name))?;
64
65        // Check bounds
66        if let Some(max) = self.max_value {
67            if self.increment_by > 0 && next > max {
68                if self.cycle {
69                    self.current_value = self.min_value.unwrap_or(self.start_with);
70                } else {
71                    self.exhausted = true;
72                }
73                return Ok(value);
74            }
75        }
76
77        if let Some(min) = self.min_value {
78            if self.increment_by < 0 && next < min {
79                if self.cycle {
80                    self.current_value = self.max_value.unwrap_or(self.start_with);
81                } else {
82                    self.exhausted = true;
83                }
84                return Ok(value);
85            }
86        }
87
88        self.current_value = next;
89        Ok(value)
90    }
91
92    /// Restart the sequence
93    pub fn restart(&mut self, value: Option<i64>) {
94        self.current_value = value.unwrap_or(self.start_with);
95        self.exhausted = false;
96    }
97}
98
99impl Default for Sequence {
100    fn default() -> Self {
101        Sequence {
102            name: String::new(),
103            start_with: 1,
104            increment_by: 1,
105            min_value: None,
106            max_value: None,
107            cycle: false,
108            current_value: 1,
109            exhausted: false,
110        }
111    }
112}
113
114/// User-defined Type (UDT)
115#[derive(Debug, Clone, Default)]
116pub struct UserDefinedType {
117    pub name: String,
118    // TODO: Add fields when implementing full functionality
119}
120
121impl UserDefinedType {
122    pub fn new(name: String) -> Self {
123        UserDefinedType { name }
124    }
125}
126
127/// Collation - String comparison rules
128#[derive(Debug, Clone, Default)]
129pub struct Collation {
130    pub name: String,
131    pub character_set: Option<String>,    // FOR character_set
132    pub source_collation: Option<String>, // FROM source_collation
133    pub pad_space: Option<bool>,          // PAD SPACE (true) | NO PAD (false)
134}
135
136impl Collation {
137    pub fn new(
138        name: String,
139        character_set: Option<String>,
140        source_collation: Option<String>,
141        pad_space: Option<bool>,
142    ) -> Self {
143        Collation { name, character_set, source_collation, pad_space }
144    }
145}
146
147/// Character Set - Character encoding
148#[derive(Debug, Clone, Default)]
149pub struct CharacterSet {
150    pub name: String,
151    pub source: Option<String>,    // GET source
152    pub collation: Option<String>, // COLLATE FROM collation
153}
154
155impl CharacterSet {
156    pub fn new(name: String, source: Option<String>, collation: Option<String>) -> Self {
157        CharacterSet { name, source, collation }
158    }
159}
160
161/// Translation - Character set translation
162#[derive(Debug, Clone, Default)]
163pub struct Translation {
164    pub name: String,
165    pub source_charset: Option<String>,     // FOR source_charset
166    pub target_charset: Option<String>,     // TO target_charset
167    pub translation_source: Option<String>, // FROM translation_source
168}
169
170impl Translation {
171    pub fn new(
172        name: String,
173        source_charset: Option<String>,
174        target_charset: Option<String>,
175        translation_source: Option<String>,
176    ) -> Self {
177        Translation { name, source_charset, target_charset, translation_source }
178    }
179}
180
181/// Assertion - Named constraint that checks a boolean condition (SQL:1999 Feature F671/F672)
182///
183/// Assertions are schema-level constraints that can reference multiple tables
184/// and enforce complex integrity rules across the database.
185#[derive(Debug, Clone)]
186pub struct Assertion {
187    pub name: String,
188    pub check_condition: vibesql_ast::Expression,
189}
190
191impl Assertion {
192    pub fn new(name: String, check_condition: vibesql_ast::Expression) -> Self {
193        Assertion { name, check_condition }
194    }
195}
196
197/// Function - Stored function (SQL:1999 Feature P001)
198#[derive(Debug, Clone)]
199pub struct Function {
200    pub name: String,
201    pub schema: String,
202    pub parameters: Vec<FunctionParam>,
203    pub return_type: vibesql_types::DataType,
204    pub body: FunctionBody,
205    // Characteristics (Phase 6)
206    pub deterministic: bool,
207    pub sql_security: SqlSecurity,
208    pub comment: Option<String>,
209    pub language: String,
210}
211
212impl Function {
213    pub fn new(
214        name: String,
215        schema: String,
216        parameters: Vec<FunctionParam>,
217        return_type: vibesql_types::DataType,
218        body: FunctionBody,
219    ) -> Self {
220        Function {
221            name,
222            schema,
223            parameters,
224            return_type,
225            body,
226            // Default characteristics
227            deterministic: false,
228            sql_security: SqlSecurity::Definer,
229            comment: None,
230            language: "SQL".to_string(),
231        }
232    }
233
234    #[allow(clippy::too_many_arguments)]
235    pub fn with_characteristics(
236        name: String,
237        schema: String,
238        parameters: Vec<FunctionParam>,
239        return_type: vibesql_types::DataType,
240        body: FunctionBody,
241        deterministic: bool,
242        sql_security: SqlSecurity,
243        comment: Option<String>,
244        language: String,
245    ) -> Self {
246        Function {
247            name,
248            schema,
249            parameters,
250            return_type,
251            body,
252            deterministic,
253            sql_security,
254            comment,
255            language,
256        }
257    }
258}
259
260/// Parameter in a function definition
261#[derive(Debug, Clone)]
262pub struct FunctionParam {
263    pub name: String,
264    pub data_type: vibesql_types::DataType,
265}
266
267/// Body of a function
268#[derive(Debug, Clone)]
269pub enum FunctionBody {
270    /// SQL procedural block: BEGIN ... END
271    BeginEnd(String), // Stored as raw SQL for now
272    /// Raw SQL for simpler cases
273    RawSql(String),
274}
275
276/// Procedure - Stored procedure (SQL:1999 Feature P001)
277#[derive(Debug, Clone)]
278pub struct Procedure {
279    pub name: String,
280    pub schema: String,
281    pub parameters: Vec<ProcedureParam>,
282    pub body: ProcedureBody,
283    // Characteristics (Phase 6)
284    pub sql_security: SqlSecurity,
285    pub comment: Option<String>,
286    pub language: String,
287}
288
289impl Procedure {
290    pub fn new(
291        name: String,
292        schema: String,
293        parameters: Vec<ProcedureParam>,
294        body: ProcedureBody,
295    ) -> Self {
296        Procedure {
297            name,
298            schema,
299            parameters,
300            body,
301            // Default characteristics
302            sql_security: SqlSecurity::Definer,
303            comment: None,
304            language: "SQL".to_string(),
305        }
306    }
307
308    pub fn with_characteristics(
309        name: String,
310        schema: String,
311        parameters: Vec<ProcedureParam>,
312        body: ProcedureBody,
313        sql_security: SqlSecurity,
314        comment: Option<String>,
315        language: String,
316    ) -> Self {
317        Procedure { name, schema, parameters, body, sql_security, comment, language }
318    }
319}
320
321/// Parameter in a procedure definition
322#[derive(Debug, Clone)]
323pub struct ProcedureParam {
324    pub mode: ParameterMode,
325    pub name: String,
326    pub data_type: vibesql_types::DataType,
327}
328
329/// Parameter mode: IN, OUT, or INOUT
330#[derive(Debug, Clone, PartialEq)]
331pub enum ParameterMode {
332    In,
333    Out,
334    InOut,
335}
336
337/// SQL SECURITY characteristic for procedures and functions (Phase 6)
338#[derive(Debug, Clone, PartialEq)]
339pub enum SqlSecurity {
340    Definer,
341    Invoker,
342}
343
344/// Body of a procedure
345#[derive(Debug, Clone)]
346pub enum ProcedureBody {
347    /// SQL procedural block: BEGIN ... END
348    /// Stores the parsed AST of procedural statements for execution
349    BeginEnd(Vec<vibesql_ast::ProceduralStatement>),
350    /// Raw SQL for simpler cases (legacy/fallback)
351    RawSql(String),
352}