sea_query/backend/sqlite/
table.rs1use super::*;
2
3impl TableBuilder for SqliteQueryBuilder {
4 fn prepare_column_def(&self, column_def: &ColumnDef, sql: &mut dyn SqlWriter) {
5 self.prepare_iden(&column_def.name, sql);
6
7 if let Some(column_type) = &column_def.types {
8 sql.write_str(" ").unwrap();
9 self.prepare_column_type(&column_def.spec, column_type, sql);
10 }
11
12 let mut is_primary_key = false;
13 let mut is_auto_increment = false;
14
15 for column_spec in column_def.spec.iter() {
16 if matches!(column_spec, ColumnSpec::PrimaryKey) {
17 is_primary_key = true;
18 continue;
19 }
20 if matches!(column_spec, ColumnSpec::AutoIncrement) {
21 is_auto_increment = true;
22 continue;
23 }
24 if let ColumnSpec::Comment(_) = column_spec {
25 continue;
26 }
27 sql.write_str(" ").unwrap();
28 self.prepare_column_spec(column_spec, sql);
29 }
30
31 if is_primary_key {
32 sql.write_str(" ").unwrap();
33 self.prepare_column_spec(&ColumnSpec::PrimaryKey, sql);
34 }
35 if is_auto_increment {
36 sql.write_str(" ").unwrap();
37 self.prepare_column_spec(&ColumnSpec::AutoIncrement, sql);
38 }
39 }
40
41 fn prepare_column_type(&self, column_type: &ColumnType, sql: &mut dyn SqlWriter) {
42 self.prepare_column_type(&[], column_type, sql)
43 }
44
45 fn column_spec_auto_increment_keyword(&self) -> &str {
46 "AUTOINCREMENT"
47 }
48
49 fn prepare_table_drop_opt(&self, _drop_opt: &TableDropOpt, _sql: &mut dyn SqlWriter) {
50 }
52
53 fn prepare_table_truncate_statement(
54 &self,
55 _truncate: &TableTruncateStatement,
56 _sql: &mut dyn SqlWriter,
57 ) {
58 panic!("Sqlite doesn't support TRUNCATE statement")
59 }
60
61 fn prepare_table_alter_statement(&self, alter: &TableAlterStatement, sql: &mut dyn SqlWriter) {
62 if alter.options.is_empty() {
63 panic!("No alter option found")
64 }
65 if alter.options.len() > 1 {
66 panic!("Sqlite doesn't support multiple alter options")
67 }
68 sql.write_str("ALTER TABLE ").unwrap();
69 if let Some(table) = &alter.table {
70 self.prepare_table_ref_table_stmt(table, sql);
71 sql.write_str(" ").unwrap();
72 }
73 match &alter.options[0] {
74 TableAlterOption::AddColumn(AddColumnOption {
75 column,
76 if_not_exists: _,
77 }) => {
78 sql.write_str("ADD COLUMN ").unwrap();
79 self.prepare_column_def(column, sql);
80 }
81 TableAlterOption::ModifyColumn(_) => {
82 panic!("Sqlite not support modifying table column")
83 }
84 TableAlterOption::RenameColumn(from_name, to_name) => {
85 sql.write_str("RENAME COLUMN ").unwrap();
86 self.prepare_iden(from_name, sql);
87 sql.write_str(" TO ").unwrap();
88 self.prepare_iden(to_name, sql);
89 }
90 TableAlterOption::DropColumn(col_name) => {
91 sql.write_str("DROP COLUMN ").unwrap();
92 self.prepare_iden(col_name, sql);
93 }
94 TableAlterOption::DropForeignKey(_) => {
95 panic!(
96 "Sqlite does not support modification of foreign key constraints to existing tables"
97 );
98 }
99 TableAlterOption::AddForeignKey(_) => {
100 panic!(
101 "Sqlite does not support modification of foreign key constraints to existing tables"
102 );
103 }
104 }
105 }
106
107 fn prepare_table_rename_statement(
108 &self,
109 rename: &TableRenameStatement,
110 sql: &mut dyn SqlWriter,
111 ) {
112 sql.write_str("ALTER TABLE ").unwrap();
113 if let Some(from_name) = &rename.from_name {
114 self.prepare_table_ref_table_stmt(from_name, sql);
115 }
116 sql.write_str(" RENAME TO ").unwrap();
117 if let Some(to_name) = &rename.to_name {
118 self.prepare_table_ref_table_stmt(to_name, sql);
119 }
120 }
121}
122
123impl SqliteQueryBuilder {
124 fn prepare_column_type(
125 &self,
126 column_specs: &[ColumnSpec],
127 column_type: &ColumnType,
128 sql: &mut dyn SqlWriter,
129 ) {
130 let is_auto_increment = column_specs
131 .iter()
132 .any(|s| matches!(s, ColumnSpec::AutoIncrement));
133 match column_type {
134 ColumnType::Char(length) => match length {
135 Some(length) => {
136 sql.write_str("char(").unwrap();
137 write!(sql, "{length}").unwrap();
138 sql.write_char(')')
139 }
140 None => sql.write_str("char"),
141 },
142 ColumnType::String(length) => match length {
143 StringLen::N(length) => {
144 sql.write_str("varchar(").unwrap();
145 write!(sql, "{length}").unwrap();
146 sql.write_char(')')
147 }
148 _ => sql.write_str("varchar"),
149 },
150 ColumnType::Text => sql.write_str("text"),
151 ColumnType::TinyInteger | ColumnType::TinyUnsigned => sql.write_str(integer("tinyint")),
152 ColumnType::SmallInteger | ColumnType::SmallUnsigned => {
153 sql.write_str(integer("smallint"))
154 }
155 ColumnType::Integer | ColumnType::Unsigned => sql.write_str("integer"),
156 #[allow(clippy::if_same_then_else)]
157 ColumnType::BigInteger | ColumnType::BigUnsigned => {
158 if is_auto_increment {
159 sql.write_str("integer")
160 } else {
161 sql.write_str(integer("bigint"))
162 }
163 }
164 ColumnType::Float => sql.write_str("float"),
165 ColumnType::Double => sql.write_str("double"),
166 ColumnType::Decimal(precision) => match precision {
167 Some((precision, scale)) => {
168 if precision > &16 {
169 panic!("precision cannot be larger than 16");
170 }
171 sql.write_str("real(").unwrap();
172 write!(sql, "{precision}").unwrap();
173 sql.write_str(", ").unwrap();
174 write!(sql, "{scale}").unwrap();
175 sql.write_char(')')
176 }
177 None => sql.write_str("real"),
178 },
179 ColumnType::DateTime => sql.write_str("datetime_text"),
180 ColumnType::Timestamp => sql.write_str("timestamp_text"),
181 ColumnType::TimestampWithTimeZone => sql.write_str("timestamp_with_timezone_text"),
182 ColumnType::Time => sql.write_str("time_text"),
183 ColumnType::Date => sql.write_str("date_text"),
184 ColumnType::Interval(_, _) => unimplemented!("Interval is not available in Sqlite."),
185 ColumnType::Binary(length) => {
186 sql.write_str("blob(").unwrap();
187 write!(sql, "{length}").unwrap();
188 sql.write_char(')')
189 }
190 ColumnType::VarBinary(length) => match length {
191 StringLen::N(length) => {
192 sql.write_str("varbinary_blob(").unwrap();
193 write!(sql, "{length}").unwrap();
194 sql.write_char(')')
195 }
196 _ => sql.write_str("varbinary_blob"),
197 },
198 ColumnType::Blob => sql.write_str("blob"),
199 ColumnType::Boolean => sql.write_str("boolean"),
200 ColumnType::Money(precision) => match precision {
201 Some((precision, scale)) => {
202 sql.write_str("real_money(").unwrap();
203 write!(sql, "{precision}").unwrap();
204 sql.write_str(", ").unwrap();
205 write!(sql, "{scale}").unwrap();
206 sql.write_char(')')
207 }
208 None => sql.write_str("real_money"),
209 },
210 ColumnType::Json => sql.write_str("json_text"),
211 ColumnType::JsonBinary => sql.write_str("jsonb_text"),
212 ColumnType::Uuid => sql.write_str("uuid_text"),
213 ColumnType::Custom(iden) => sql.write_str(&iden.0),
214 ColumnType::Enum { .. } => sql.write_str("enum_text"),
215 ColumnType::Array(_) => unimplemented!("Array is not available in Sqlite."),
216 ColumnType::Vector(_) => unimplemented!("Vector is not available in Sqlite."),
217 ColumnType::Cidr => unimplemented!("Cidr is not available in Sqlite."),
218 ColumnType::Inet => unimplemented!("Inet is not available in Sqlite."),
219 ColumnType::MacAddr => unimplemented!("MacAddr is not available in Sqlite."),
220 ColumnType::Year => unimplemented!("Year is not available in Sqlite."),
221 ColumnType::Bit(_) => unimplemented!("Bit is not available in Sqlite."),
222 ColumnType::VarBit(_) => unimplemented!("VarBit is not available in Sqlite."),
223 ColumnType::LTree => unimplemented!("LTree is not available in Sqlite."),
224 }
225 .unwrap()
226 }
227}
228
229fn integer(ty: &str) -> &str {
230 if cfg!(feature = "option-sqlite-exact-column-type") {
231 "integer"
232 } else {
233 ty
234 }
235}