lumus_sql_builder/sqlite/
columns.rs

1use super::BuildableStatement;
2use crate::errors::SqlBuilderError;
3
4/// Represents the possible data types for a table column.
5#[derive(Debug)]
6pub enum ColumnType {
7    Integer,
8    Text,
9    Real,
10    Boolean,
11    Blob,
12    Numeric,
13    Date,
14    Time,
15    Datetime,
16}
17
18/// Implementation of the `BuildableStatement` trait for `ColumnType`, allowing it to be printed.
19impl BuildableStatement for ColumnType {
20    fn build(&self) -> String {
21        String::from(match self {
22            Self::Integer => "INTEGER",
23            Self::Text => "TEXT",
24            Self::Real => "REAL",
25            Self::Boolean => "BOOLEAN",
26            Self::Blob => "BLOB",
27            Self::Numeric => "NUMERIC",
28            Self::Date => "DATE",
29            Self::Time => "TIME",
30            Self::Datetime => "DATETIME",
31        })
32    }
33}
34
35/// Represents the possible options for a table column.
36#[derive(Debug)]
37pub enum ColumnOption {
38    NotNull,
39    Unique,
40    Default(String),
41    AutoIncrement,
42    PrimaryKey,
43}
44
45/// Implementation of the `BuildableStatement` trait for `ColumnOption`, allowing it to be printed.
46impl BuildableStatement for ColumnOption {
47    fn build(&self) -> String {
48        match self {
49            Self::NotNull => "NOT NULL".to_string(),
50            Self::Unique => "UNIQUE".to_string(),
51            Self::Default(s) => format!("DEFAULT {}", s),
52            Self::AutoIncrement => "AUTOINCREMENT".to_string(),
53            Self::PrimaryKey => "PRIMARY KEY".to_string(),
54        }
55    }
56}
57
58/// Represents a table column with a name, data type, and options.
59#[derive(Debug)]
60pub struct Column {
61    name: String,
62    column_type: Option<ColumnType>,
63    options: Vec<ColumnOption>,
64}
65
66impl Column {
67    /// Creates a new `Column` instance with the given column name.
68    /// # Example
69    /// ```
70    /// use lumus_sql_builder::sqlite::Column;
71    /// let col = Column::new("name").text().not_null();
72    ///
73    /// assert_eq!(col.build().unwrap(), "name TEXT NOT NULL");
74    /// ```
75    pub fn new(name: &str) -> Self {
76        Self {
77            name: name.to_string(),
78            column_type: None,
79            options: Vec::new(),
80        }
81    }
82
83    /// Specifies that the column has an `INTEGER` data type.
84    pub fn integer(mut self) -> Self {
85        self.column_type = Some(ColumnType::Integer);
86        self
87    }
88
89    /// Specifies that the column has a `TEXT` data type.
90    pub fn text(mut self) -> Self {
91        self.column_type = Some(ColumnType::Text);
92        self
93    }
94
95    /// Specifies that the column has a `REAL` data type.
96    pub fn real(mut self) -> Self {
97        self.column_type = Some(ColumnType::Real);
98        self
99    }
100
101    /// Specifies that the column has a `BOOLEAN` data type.
102    pub fn boolean(mut self) -> Self {
103        self.column_type = Some(ColumnType::Boolean);
104        self
105    }
106
107    /// Specifies that the column has a `BLOB` data type.
108    pub fn blob(mut self) -> Self {
109        self.column_type = Some(ColumnType::Blob);
110        self
111    }
112
113    /// Specifies that the column has a `NUMERIC` data type.
114    pub fn numeric(mut self) -> Self {
115        self.column_type = Some(ColumnType::Numeric);
116        self
117    }
118
119    /// Specifies that the column has a `DATE` data type.
120    pub fn date(mut self) -> Self {
121        self.column_type = Some(ColumnType::Date);
122        self
123    }
124
125    /// Specifies that the column has a `TIME` data type.
126    pub fn time(mut self) -> Self {
127        self.column_type = Some(ColumnType::Time);
128        self
129    }
130
131    /// Specifies that the column has a `DATETIME` data type.
132    pub fn datetime(mut self) -> Self {
133        self.column_type = Some(ColumnType::Datetime);
134        self
135    }
136
137    /// Specifies that the column cannot have `NULL` values.
138    pub fn not_null(mut self) -> Self {
139        self.options.push(ColumnOption::NotNull);
140        self
141    }
142
143    /// Specifies that the column values must be unique across rows.
144    pub fn unique(mut self) -> Self {
145        self.options.push(ColumnOption::Unique);
146        self
147    }
148
149    /// Specifies a default value for the column.
150    pub fn default(mut self, value: &str) -> Self {
151        self.options.push(ColumnOption::Default(value.to_string()));
152        self
153    }
154
155    /// Specifies that the column values should auto-increment.
156    pub fn auto_increment(mut self) -> Self {
157        self.options.push(ColumnOption::AutoIncrement);
158        self
159    }
160
161    /// Specifies that the column is a primary key.
162    pub fn primary_key(mut self) -> Self {
163        self.options.push(ColumnOption::PrimaryKey);
164        self
165    }
166
167    /// Builds and returns the SQL representation of the column.
168    pub fn build(&self) -> Result<String, SqlBuilderError> {
169        if self.name.is_empty() {
170            return Err(SqlBuilderError::EmptyColumnName);
171        }
172
173        let column_type = match &self.column_type {
174            Some(ct) => ct.build(),
175            None => return Err(SqlBuilderError::InvalidColumnType),
176        };
177
178        let options_str = self
179            .options
180            .iter()
181            .map(|opt| opt.build())
182            .collect::<Vec<String>>()
183            .join(" ");
184
185        Ok(format!("{} {} {}", self.name, column_type, options_str))
186    }
187}
188
189/// Implementation of the `BuildableStatement` trait for `Column`, allowing it to be printed.
190impl BuildableStatement for Column {
191    fn build(&self) -> String {
192        self.build().unwrap()
193    }
194}