1use super::DefaultType;
2use crate::{sqlite::def::ColumnVisibility, sqlx_types::SqlxRow};
3use sea_query::{
4 Alias, ColumnType, Index, IndexCreateStatement,
5 foreign_key::ForeignKeyAction as SeaQueryForeignKeyAction,
6};
7use std::num::ParseIntError;
8
9#[derive(Debug, PartialEq, Clone)]
11pub struct ColumnInfo {
12 pub cid: i64,
14 pub name: String,
16 pub r#type: ColumnType,
18 pub not_null: bool,
20 pub default_value: DefaultType,
21 pub primary_key: bool,
23 pub hidden: ColumnVisibility,
25}
26
27#[cfg(feature = "sqlx-sqlite")]
28impl ColumnInfo {
29 pub fn to_column_def(row: SqlxRow) -> Result<ColumnInfo, ParseIntError> {
31 use crate::sqlx_types::Row;
32 let row = row.sqlite();
33 let col_not_null: i8 = row.get(3);
34 let is_pk: i8 = row.get(5);
35 let default_value: Option<String> = row.get(4);
36 let default_value = default_value.unwrap_or_default();
37 let hidden: i8 = row.get(6);
38 Ok(ColumnInfo {
39 cid: row.get(0),
40 name: row.get(1),
41 r#type: super::parse_type(row.get(2))?,
42 not_null: col_not_null != 0 || is_pk == 1,
43 default_value: if default_value == "NULL" {
44 DefaultType::Null
45 } else if default_value.is_empty() {
46 DefaultType::Unspecified
47 } else {
48 let value = default_value.to_owned().replace('\'', "");
49
50 if let Ok(is_int) = value.parse::<i64>() {
51 DefaultType::Integer(is_int)
52 } else if let Ok(is_float) = value.parse::<f32>() {
53 DefaultType::Float(is_float)
54 } else if value == "CURRENT_TIMESTAMP" {
55 DefaultType::CurrentTimestamp
56 } else {
57 DefaultType::String(value)
58 }
59 },
60 primary_key: is_pk != 0,
61 hidden: ColumnVisibility::from_hidden(hidden),
62 })
63 }
64
65 #[inline]
66 pub fn is_hidden(&self) -> bool {
67 self.hidden == ColumnVisibility::HiddenVirtual
68 }
69}
70
71#[cfg(not(feature = "sqlx-sqlite"))]
72impl ColumnInfo {
73 pub fn to_column_def(_: SqlxRow) -> Result<ColumnInfo, ParseIntError> {
74 unimplemented!()
75 }
76
77 #[inline]
78 pub fn is_hidden(&self) -> bool {
79 unimplemented!()
80 }
81}
82
83#[derive(Debug, Default, Clone, PartialEq)]
87pub struct IndexInfo {
88 pub r#type: String,
90 pub index_name: String,
91 pub table_name: String,
92 pub unique: bool,
93 pub origin: String,
94 pub partial: i64,
95 pub columns: Vec<String>,
96}
97
98impl IndexInfo {
99 pub fn write(&self) -> IndexCreateStatement {
101 let mut new_index = Index::create();
102 if self.origin.as_str() == "c" {
104 new_index.name(&self.index_name);
105 }
106 new_index.table(Alias::new(&self.table_name));
107
108 if self.unique {
109 new_index.unique();
110 }
111
112 self.columns.iter().for_each(|column| {
113 new_index.col(Alias::new(column));
114 });
115
116 new_index
117 }
118}
119
120#[allow(dead_code)]
123#[derive(Debug, Default, Clone)]
124pub(crate) struct PartialIndexInfo {
125 pub(crate) seq: i64,
126 pub(crate) name: String,
127 pub(crate) unique: bool,
128 pub(crate) origin: String,
129 pub(crate) partial: i64,
130}
131
132#[cfg(feature = "sqlx-sqlite")]
133impl From<SqlxRow> for PartialIndexInfo {
134 fn from(row: SqlxRow) -> Self {
135 use crate::sqlx_types::Row;
136 let row = row.sqlite();
137 let is_unique: i8 = row.get(2);
138 Self {
139 seq: row.get(0),
140 name: row.get(1),
141 unique: is_unique != 0,
142 origin: row.get(3),
143 partial: row.get(4),
144 }
145 }
146}
147
148#[cfg(not(feature = "sqlx-sqlite"))]
149impl From<SqlxRow> for PartialIndexInfo {
150 fn from(_: SqlxRow) -> Self {
151 Self::default()
152 }
153}
154
155#[allow(dead_code)]
158#[derive(Debug, Default, Clone)]
159pub(crate) struct IndexedColumns {
160 pub(crate) r#type: String,
161 pub(crate) name: String,
162 pub(crate) table: String,
163 pub(crate) root_page: i64,
164 pub(crate) indexed_columns: Vec<String>,
165}
166
167#[cfg(feature = "sqlx-sqlite")]
168impl From<(SqlxRow, Vec<SqlxRow>)> for IndexedColumns {
169 fn from((row, rows): (SqlxRow, Vec<SqlxRow>)) -> Self {
170 use crate::sqlx_types::Row;
171
172 let row = row.sqlite();
173 let columns_to_index = rows
174 .into_iter()
175 .map(|r| r.sqlite().get(2))
176 .collect::<Vec<String>>();
177
178 Self {
179 r#type: row.get(0),
180 name: row.get(1),
181 table: row.get(2),
182 root_page: row.get(3),
183 indexed_columns: columns_to_index,
184 }
185 }
186}
187
188#[cfg(not(feature = "sqlx-sqlite"))]
189impl From<(SqlxRow, Vec<SqlxRow>)> for IndexedColumns {
190 fn from(_: (SqlxRow, Vec<SqlxRow>)) -> Self {
191 Self::default()
192 }
193}
194
195#[allow(dead_code)]
198#[derive(Debug, Default, Clone)]
199pub(crate) struct PrimaryKeyAutoincrement(pub(crate) u8);
200
201#[cfg(feature = "sqlx-sqlite")]
202impl From<SqlxRow> for PrimaryKeyAutoincrement {
203 fn from(row: SqlxRow) -> Self {
204 use crate::sqlx_types::Row;
205 Self(row.sqlite().get(0))
206 }
207}
208
209#[cfg(not(feature = "sqlx-sqlite"))]
210impl From<SqlxRow> for PrimaryKeyAutoincrement {
211 fn from(_: SqlxRow) -> Self {
212 Self::default()
213 }
214}
215
216#[derive(Debug, Default, Clone, PartialEq)]
218#[non_exhaustive]
219pub struct ForeignKeysInfo {
220 pub id: i64,
221 pub seq: i64,
222 pub table: String,
223 pub from: Vec<String>,
224 pub to: Vec<String>,
225 pub on_update: ForeignKeyAction,
226 pub on_delete: ForeignKeyAction,
227 pub r#match: MatchAction,
228}
229
230#[cfg(feature = "sqlx-sqlite")]
231impl From<SqlxRow> for ForeignKeysInfo {
232 fn from(row: SqlxRow) -> Self {
233 use crate::sqlx_types::Row;
234 let row = row.sqlite();
235 Self {
236 id: row.get(0),
237 seq: row.get(1),
238 table: row.get(2),
239 from: vec![row.get(3)],
240 to: vec![row.get(4)],
241 on_update: {
242 let op: String = row.get(5);
243 op.as_str().into()
244 },
245 on_delete: {
246 let op: String = row.get(6);
247 op.as_str().into()
248 },
249 r#match: {
250 let op: String = row.get(7);
251 op.as_str().into()
252 },
253 }
254 }
255}
256
257#[cfg(not(feature = "sqlx-sqlite"))]
258impl From<SqlxRow> for ForeignKeysInfo {
259 fn from(_: SqlxRow) -> Self {
260 Self::default()
261 }
262}
263
264#[derive(Debug, Default, PartialEq, Eq, Clone)]
266pub enum ForeignKeyAction {
267 #[default]
268 NoAction,
269 Restrict,
270 SetNull,
271 SetDefault,
272 Cascade,
273}
274
275impl From<&str> for ForeignKeyAction {
276 fn from(action: &str) -> Self {
277 match action {
278 "NO ACTION" => Self::NoAction,
279 "RESTRICT" => Self::Restrict,
280 "SET NULL" => Self::SetNull,
281 "SET DEFAULT" => Self::SetDefault,
282 "CASCADE" => Self::Cascade,
283 _ => Self::NoAction,
284 }
285 }
286}
287
288impl ForeignKeyAction {
289 pub(crate) fn to_seaquery_foreign_key_action(&self) -> SeaQueryForeignKeyAction {
290 match self {
291 Self::NoAction => SeaQueryForeignKeyAction::NoAction,
292 Self::Restrict => SeaQueryForeignKeyAction::Restrict,
293 Self::SetNull => SeaQueryForeignKeyAction::SetNull,
294 Self::SetDefault => SeaQueryForeignKeyAction::SetDefault,
295 Self::Cascade => SeaQueryForeignKeyAction::Cascade,
296 }
297 }
298}
299
300#[derive(Debug, Default, PartialEq, Eq, Clone)]
302pub enum MatchAction {
303 Simple,
304 Partial,
305 Full,
306 #[default]
307 None,
308}
309
310impl From<&str> for MatchAction {
311 fn from(action: &str) -> Self {
312 match action {
313 "MATCH SIMPLE" => Self::Simple,
314 "MATCH PARTIAL" => Self::Partial,
315 "MATCH FULL" => Self::Full,
316 "MATCH NONE" => Self::None,
317 _ => Self::None,
318 }
319 }
320}