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 column_def.name.prepare(sql.as_writer(), self.quote());
6
7 if let Some(column_type) = &column_def.types {
8 write!(sql, " ").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 let ColumnSpec::PrimaryKey = column_spec {
17 is_primary_key = true;
18 continue;
19 }
20 if let ColumnSpec::AutoIncrement = column_spec {
21 is_auto_increment = true;
22 continue;
23 }
24 if let ColumnSpec::Comment(_) = column_spec {
25 continue;
26 }
27 write!(sql, " ").unwrap();
28 self.prepare_column_spec(column_spec, sql);
29 }
30
31 if is_primary_key {
32 write!(sql, " ").unwrap();
33 self.prepare_column_spec(&ColumnSpec::PrimaryKey, sql);
34 }
35 if is_auto_increment {
36 write!(sql, " ").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 write!(sql, "ALTER TABLE ").unwrap();
69 if let Some(table) = &alter.table {
70 self.prepare_table_ref_table_stmt(table, sql);
71 write!(sql, " ").unwrap();
72 }
73 match &alter.options[0] {
74 TableAlterOption::AddColumn(AddColumnOption {
75 column,
76 if_not_exists: _,
77 }) => {
78 write!(sql, "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 write!(sql, "RENAME COLUMN ").unwrap();
86 from_name.prepare(sql.as_writer(), self.quote());
87 write!(sql, " TO ").unwrap();
88 to_name.prepare(sql.as_writer(), self.quote());
89 }
90 TableAlterOption::DropColumn(col_name) => {
91 write!(sql, "DROP COLUMN ").unwrap();
92 col_name.prepare(sql.as_writer(), self.quote());
93 }
94 TableAlterOption::DropForeignKey(_) => {
95 panic!("Sqlite does not support modification of foreign key constraints to existing tables");
96 }
97 TableAlterOption::AddForeignKey(_) => {
98 panic!("Sqlite does not support modification of foreign key constraints to existing tables");
99 }
100 }
101 }
102
103 fn prepare_table_rename_statement(
104 &self,
105 rename: &TableRenameStatement,
106 sql: &mut dyn SqlWriter,
107 ) {
108 write!(sql, "ALTER TABLE ").unwrap();
109 if let Some(from_name) = &rename.from_name {
110 self.prepare_table_ref_table_stmt(from_name, sql);
111 }
112 write!(sql, " RENAME TO ").unwrap();
113 if let Some(to_name) = &rename.to_name {
114 self.prepare_table_ref_table_stmt(to_name, sql);
115 }
116 }
117}
118
119impl SqliteQueryBuilder {
120 fn prepare_column_type(
121 &self,
122 column_specs: &[ColumnSpec],
123 column_type: &ColumnType,
124 sql: &mut dyn SqlWriter,
125 ) {
126 let is_auto_increment = column_specs
127 .iter()
128 .any(|s| matches!(s, ColumnSpec::AutoIncrement));
129 write!(
130 sql,
131 "{}",
132 match column_type {
133 ColumnType::Char(length) => match length {
134 Some(length) => format!("char({length})"),
135 None => "char".into(),
136 },
137 ColumnType::String(length) => match length {
138 StringLen::N(length) => format!("varchar({length})"),
139 _ => "varchar".into(),
140 },
141 ColumnType::Text => "text".into(),
142 ColumnType::TinyInteger | ColumnType::TinyUnsigned => integer("tinyint").into(),
143 ColumnType::SmallInteger | ColumnType::SmallUnsigned => integer("smallint").into(),
144 ColumnType::Integer | ColumnType::Unsigned => "integer".into(),
145 #[allow(clippy::if_same_then_else)]
146 ColumnType::BigInteger | ColumnType::BigUnsigned => if is_auto_increment {
147 "integer"
148 } else {
149 integer("bigint")
150 }
151 .into(),
152 ColumnType::Float => "float".into(),
153 ColumnType::Double => "double".into(),
154 ColumnType::Decimal(precision) => match precision {
155 Some((precision, scale)) => {
156 if precision > &16 {
157 panic!("precision cannot be larger than 16");
158 }
159 format!("real({precision}, {scale})")
160 }
161 None => "real".into(),
162 },
163 ColumnType::DateTime => "datetime_text".into(),
164 ColumnType::Timestamp => "timestamp_text".into(),
165 ColumnType::TimestampWithTimeZone => "timestamp_with_timezone_text".into(),
166 ColumnType::Time => "time_text".into(),
167 ColumnType::Date => "date_text".into(),
168 ColumnType::Interval(_, _) =>
169 unimplemented!("Interval is not available in Sqlite."),
170 ColumnType::Binary(length) => format!("blob({length})"),
171 ColumnType::VarBinary(length) => match length {
172 StringLen::N(length) => format!("varbinary_blob({length})"),
173 _ => "varbinary_blob".into(),
174 },
175 ColumnType::Blob => "blob".into(),
176 ColumnType::Boolean => "boolean".into(),
177 ColumnType::Money(precision) => match precision {
178 Some((precision, scale)) => format!("real_money({precision}, {scale})"),
179 None => "real_money".into(),
180 },
181 ColumnType::Json => "json_text".into(),
182 ColumnType::JsonBinary => "jsonb_text".into(),
183 ColumnType::Uuid => "uuid_text".into(),
184 ColumnType::Custom(iden) => iden.to_string(),
185 ColumnType::Enum { .. } => "enum_text".into(),
186 ColumnType::Array(_) => unimplemented!("Array is not available in Sqlite."),
187 ColumnType::Vector(_) => unimplemented!("Vector is not available in Sqlite."),
188 ColumnType::Cidr => unimplemented!("Cidr is not available in Sqlite."),
189 ColumnType::Inet => unimplemented!("Inet is not available in Sqlite."),
190 ColumnType::MacAddr => unimplemented!("MacAddr is not available in Sqlite."),
191 ColumnType::Year => unimplemented!("Year is not available in Sqlite."),
192 ColumnType::Bit(_) => unimplemented!("Bit is not available in Sqlite."),
193 ColumnType::VarBit(_) => unimplemented!("VarBit is not available in Sqlite."),
194 ColumnType::LTree => unimplemented!("LTree is not available in Sqlite."),
195 }
196 )
197 .unwrap()
198 }
199}
200
201fn integer(ty: &str) -> &str {
202 if cfg!(feature = "option-sqlite-exact-column-type") {
203 "integer"
204 } else {
205 ty
206 }
207}