sqlayout/
lib.rs

1//! A Library for generating SQLite-specific SQL to Initialize Databases (as in `CREATE TABLE...`).
2//! SQLite Interface agnostic, e.g. can be used with [rusqlite](https://github.com/rusqlite/rusqlite), [sqlite](https://github.com/stainless-steel/sqlite) or any other SQLite Interface.
3//!
4//! # xml-config
5//!
6//! todo
7
8//#![warn(missing_docs)]
9mod error;
10
11use std::default::Default;
12#[cfg(feature = "xml-config")]
13use serde::{Serialize, Deserialize};
14
15#[cfg(feature = "xml-config")]
16pub use quick_xml::de::{from_str, from_reader};
17
18#[cfg(feature = "rusqlite")]
19use rusqlite::{Connection, Rows, Statement, Row};
20#[cfg(feature = "rusqlite")]
21use std::fmt::Write;
22pub use error::{Error, Result};
23
24#[cfg(feature = "rusqlite")]
25use crate::error::{CheckError, ExecError};
26
27// region Test Preamble
28// these cannot be in the test mod b/c it is necessary for the test trait impls (SQLPart::possibilities)
29
30#[cfg(test)]
31fn option_iter<T: Clone>(input: Vec<Box<T>>) -> Vec<Option<T>> {
32    let mut ret: Vec<Option<T>> = input.iter().map(|boxed| Some(*boxed.clone())).collect::<Vec<Option<T>>>();
33    ret.push(None);
34    ret
35}
36
37#[cfg(all(test, feature = "xml-config"))]
38#[derive(Debug, PartialEq, Eq, Clone)]
39pub enum AnySql {
40    Schema(Schema),
41    Table(Table),
42    View(View),
43}
44
45// endregion
46
47// region Traits
48
49trait SQLPart {
50    fn part_len(&self) -> Result<usize>;
51
52    fn part_str(&self, sql: &mut String) -> Result<()>;
53
54    // todo: for no-std
55    // fn part_arr(&self, sql: &mut [u8]) -> Result<()>;
56
57    #[cfg(test)]
58    fn possibilities(illegal_variants: bool) -> Vec<Box<Self>>;
59}
60
61/// Any struct implementing this trait can be converted into an SQL statement [String].
62/// Optionally, the statement can be wrapped in an SQL Transaction and/or guarded against already existing Tables with a `...IF NOT EXISTS...` guard.
63pub trait SQLStatement {
64    /// Calculates the exact length of the statement as it is currently configured.
65    /// Any change to the configuration invalidates previously calculated lengths.
66    /// Parameters are the same as in [SQLStatement::build].
67    fn len(&mut self, transaction: bool, if_exists: bool) -> Result<usize>;
68
69    /// Builds the SQL Statement as a [String].
70    ///
71    /// Arguments:
72    ///
73    /// * `transaction`: Weather the SQL-Statement should be wrapped in a SQL-Transaction
74    /// * `if_exists`: Weather the `CREATE TABLE...` statement should include a `...IF NOT EXISTS...` guard
75    fn build(&mut self, transaction: bool, if_exists: bool) -> Result<String>;
76
77    // todo: for no-std
78    // fn build_arr(&self, arr: &mut [u8], transaction: bool) -> Result<()>;
79
80    /// Executes the [SQLStatement] on the given [Connection]
81    #[cfg(feature = "rusqlite")]
82    fn execute(&mut self, transaction: bool, if_exists: bool, conn: &Connection) -> Result<(), ExecError> {
83        let sql: String = String::with_capacity(self.len(transaction, if_exists)?);
84        conn.execute_batch(sql.as_str())?;
85        Ok(())
86    }
87
88    /// Checks the given DB for deviations from the given SQL.
89    /// If the check could not be completed, a [CheckError] is returned.
90    /// If the check was completed but found discrepancies, a [String] with a human-readable Description is returned.
91    /// If the check was completed and found no discrepancies, [None] is returned.
92    #[cfg(feature = "rusqlite")]
93    fn check_db(&mut self, conn: &Connection) -> Result<Option<String>, CheckError>;
94
95    #[cfg(all(test, feature = "xml-config"))]
96    fn to_any(self) -> AnySql;
97}
98
99// endregion
100
101// region SQLiteType
102
103/// Encodes all Column-Datatypes available in SQLite, see [here](https://www.sqlite.org/datatype3.html#type_affinity).
104#[derive(Debug, Clone, Copy, PartialEq, Eq)]
105#[cfg_attr(
106    feature = "xml-config",
107    derive(Serialize, Deserialize),
108    serde(rename_all = "snake_case")
109)]
110#[allow(missing_docs)]
111pub enum SQLiteType {
112    // ref. https://www.sqlite.org/datatype3.html#type_affinity
113    Blob,
114    Numeric,
115    Integer,
116    Real,
117    Text,
118}
119
120impl Default for SQLiteType {
121    fn default() -> Self {
122        // ref. https://www.sqlite.org/datatype3.html#affinity_name_examples
123        Self::Blob
124    }
125}
126
127impl SQLPart for SQLiteType {
128    fn part_len(&self) -> Result<usize> {
129        Ok(match self {
130            SQLiteType::Blob => { 4 }
131            SQLiteType::Numeric => { 7 }
132            SQLiteType::Integer => { 7 }
133            SQLiteType::Real => { 4 }
134            SQLiteType::Text => { 4 }
135        })
136    }
137
138    fn part_str(&self, sql: &mut String) -> Result<()> {
139        match self {
140            SQLiteType::Blob => { sql.push_str("BLOB") }
141            SQLiteType::Numeric => { sql.push_str("NUMERIC") }
142            SQLiteType::Integer => { sql.push_str("INTEGER") }
143            SQLiteType::Real => { sql.push_str("REAL") }
144            SQLiteType::Text => { sql.push_str("TEXT") }
145        };
146        Ok(())
147    }
148
149    #[cfg(test)]
150    fn possibilities(_: bool) -> Vec<Box<Self>> {
151        vec![Box::new(Self::Blob), Box::new(Self::Numeric), Box::new(Self::Integer), Box::new(Self::Real), Box::new(Self::Text)]
152    }
153}
154
155// endregion
156
157// region Order
158
159/// [PrimaryKey] direction
160#[derive(Debug, Clone, Copy, PartialEq, Eq)]
161#[cfg_attr(
162    feature = "xml-config",
163    derive(Serialize, Deserialize),
164    serde(rename_all = "snake_case")
165)]
166#[allow(missing_docs)]
167pub enum Order {
168    Ascending,
169    Descending,
170}
171
172impl Default for Order {
173    fn default() -> Self {
174        Self::Ascending
175    }
176}
177
178impl SQLPart for Order {
179    fn part_len(&self) -> Result<usize> {
180        Ok(match self {
181            Order::Ascending => { 3 }
182            Order::Descending => { 4 }
183        })
184    }
185
186    fn part_str(&self, sql: &mut String) -> Result<()> {
187        match self {
188            Order::Ascending => { sql.push_str("ASC") }
189            Order::Descending => { sql.push_str("DESC") }
190        }
191        Ok(())
192    }
193
194    #[cfg(test)]
195    fn possibilities(_: bool) -> Vec<Box<Self>> {
196        vec![Box::new(Self::Ascending), Box::new(Self::Descending)]
197    }
198}
199
200// endregion
201
202// region OnConflict
203
204/// Reaction to a violated Constraint, used by [PrimaryKey], [NotNull] and [Unique].
205/// See also [here](https://www.sqlite.org/lang_conflict.html)
206#[derive(Debug, Clone, Copy, PartialEq, Eq)]
207#[cfg_attr(
208    feature = "xml-config",
209    derive(Serialize, Deserialize),
210    serde(rename_all = "snake_case")
211)]
212#[allow(missing_docs)]
213pub enum OnConflict {
214    Rollback,
215    Abort,
216    Fail,
217    Ignore,
218    Replace,
219}
220
221impl Default for OnConflict {
222    fn default() -> Self {
223        // ref. https://www.sqlite.org/lang_conflict.html
224        Self::Abort
225    }
226}
227
228impl SQLPart for OnConflict {
229    fn part_len(&self) -> Result<usize> {
230        Ok(match self {
231            OnConflict::Rollback => { 12 + 8 }
232            OnConflict::Abort => { 12 + 5 }
233            OnConflict::Fail => { 12 + 4 }
234            OnConflict::Ignore => { 12 + 6 }
235            OnConflict::Replace => { 12 + 7 }
236        })
237    }
238
239    fn part_str(&self, sql: &mut String) -> Result<()> {
240        match self {
241            OnConflict::Rollback => { sql.push_str("ON CONFLICT ROLLBACK") }
242            OnConflict::Abort => { sql.push_str("ON CONFLICT ABORT") }
243            OnConflict::Fail => { sql.push_str("ON CONFLICT FAIL") }
244            OnConflict::Ignore => { sql.push_str("ON CONFLICT IGNORE") }
245            OnConflict::Replace => { sql.push_str("ON CONFLICT REPLACE") }
246        };
247        Ok(())
248    }
249
250    #[cfg(test)]
251    fn possibilities(_: bool) -> Vec<Box<Self>> {
252        vec![Box::new(Self::Rollback), Box::new(Self::Abort), Box::new(Self::Fail), Box::new(Self::Ignore), Box::new(Self::Replace)]
253    }
254}
255
256// endregion
257
258// region FK OnAction
259
260/// Reaction to an action on a Column with a [ForeignKey]
261/// See also [here](https://www.sqlite.org/foreignkeys.html#fk_actions)
262#[derive(Debug, Clone, Copy, PartialEq, Eq)]
263#[cfg_attr(feature = "xml-config", derive(Serialize, Deserialize))]
264#[allow(missing_docs)]
265pub enum FKOnAction {
266    SetNull,
267    SetDefault,
268    Cascade,
269    Restrict,
270    NoAction,
271}
272
273impl Default for FKOnAction {
274    fn default() -> Self {
275        // ref. https://www.sqlite.org/foreignkeys.html#fk_actions
276        Self::NoAction
277    }
278}
279
280impl SQLPart for FKOnAction {
281    fn part_len(&self) -> Result<usize> {
282        Ok(match self {
283            FKOnAction::SetNull => { 8 } // space
284            FKOnAction::SetDefault => { 11 } // space
285            FKOnAction::Cascade => { 7 }
286            FKOnAction::Restrict => { 8 }
287            FKOnAction::NoAction => { 9 } // space
288        })
289    }
290
291    fn part_str(&self, sql: &mut String) -> Result<()> {
292        match self {
293            FKOnAction::SetNull => { sql.push_str("SET NULL") }
294            FKOnAction::SetDefault => { sql.push_str("SET DEFAULT") }
295            FKOnAction::Cascade => { sql.push_str("CASCADE") }
296            FKOnAction::Restrict => { sql.push_str("RESTRICT") }
297            FKOnAction::NoAction => { sql.push_str("NO ACTION") }
298        };
299        Ok(())
300    }
301
302    #[cfg(test)]
303    fn possibilities(_: bool) -> Vec<Box<Self>> {
304        vec![Box::new(Self::SetNull), Box::new(Self::SetDefault), Box::new(Self::Cascade), Box::new(Self::Restrict), Box::new(Self::NoAction)]
305    }
306}
307
308// endregion
309
310// region Generated as
311
312/// Weather a generated column should store its values or compute them on every access
313#[derive(Debug, Clone, Copy, PartialEq, Eq)]
314#[cfg_attr(feature = "xml-config", derive(Serialize, Deserialize))]
315#[allow(missing_docs)]
316pub enum GeneratedAs {
317    Virtual,
318    Stored,
319}
320
321impl Default for GeneratedAs {
322    fn default() -> Self {
323        Self::Virtual
324    }
325}
326
327impl SQLPart for GeneratedAs {
328    fn part_len(&self) -> Result<usize> {
329        Ok(match self {
330            GeneratedAs::Virtual => { 7 }
331            GeneratedAs::Stored => { 6 }
332        })
333    }
334
335    fn part_str(&self, sql: &mut String) -> Result<()> {
336        match self {
337            GeneratedAs::Virtual => { sql.push_str("VIRTUAL") }
338            GeneratedAs::Stored => { sql.push_str("STORED") }
339        }
340        Ok(())
341    }
342
343    #[cfg(test)]
344    fn possibilities(_: bool) -> Vec<Box<Self>> {
345        vec![Box::new(GeneratedAs::Virtual), Box::new(GeneratedAs::Stored)]
346    }
347}
348
349// endregion
350
351// region Primary Key
352
353/// Marks a Column as a Primary Key.
354/// It is an Error to have more than one Primary Key per [Table] ([Error::MultiplePrimaryKeys]).
355#[derive(Debug, Default, Clone, PartialEq, Eq)]
356#[cfg_attr(feature = "xml-config", derive(Serialize, Deserialize))]
357pub struct PrimaryKey {
358    #[cfg_attr(feature = "xml-config", serde(default, rename = "@order"))]
359    sort_order: Order,
360    #[cfg_attr(feature = "xml-config", serde(default, rename = "@on_conflict"))]
361    on_conflict: OnConflict,
362    #[cfg_attr(feature = "xml-config", serde(default, rename = "@autoincrement"))]
363    autoincrement: bool, // default false
364}
365
366impl PrimaryKey {
367    pub fn new(sort_order: Order, on_conflict: OnConflict, autoincrement: bool) -> Self {
368        Self {
369            sort_order,
370            on_conflict,
371            autoincrement,
372        }
373    }
374
375    pub fn set_sort_order(mut self, ord: Order) -> Self {
376        self.sort_order = ord;
377        self
378    }
379
380    pub fn set_on_conflict(mut self, on_conf: OnConflict) -> Self {
381        self.on_conflict = on_conf;
382        self
383    }
384
385    pub fn set_autoincrement(mut self, auto_inc: bool) -> Self {
386        self.autoincrement = auto_inc;
387        self
388    }
389}
390
391impl SQLPart for PrimaryKey {
392    fn part_len(&self) -> Result<usize> {
393        Ok(12 + self.sort_order.part_len()? + 1 + self.on_conflict.part_len()? + self.autoincrement as usize * 14)
394    }
395
396    fn part_str(&self, sql: &mut String) -> Result<()> {
397        sql.push_str("PRIMARY KEY ");
398        self.sort_order.part_str(sql)?;
399        sql.push(' ');
400        self.on_conflict.part_str(sql)?;
401        if self.autoincrement {
402            sql.push_str(" AUTOINCREMENT");
403        }
404        Ok(())
405    }
406
407    #[cfg(test)]
408    fn possibilities(_: bool) -> Vec<Box<Self>> {
409        let mut ret: Vec<Box<Self>> = Vec::new();
410        for so in Order::possibilities(false) {
411            for conf in OnConflict::possibilities(false) {
412                for auto_inc in [true, false] {
413                    ret.push(Box::new(Self::new(*so, *conf, auto_inc)))
414                }
415            }
416        }
417        ret
418    }
419}
420
421// endregion
422
423// region Not Null
424
425/// Marks a [Column] as `NOT NULL`, meaning the Column cannot contain `NULL` values and trying to insert `NULL` values is an Error.
426#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
427#[cfg_attr(feature = "xml-config", derive(Serialize, Deserialize))]
428pub struct NotNull {
429    #[cfg_attr(feature = "xml-config", serde(default, rename = "@on_conflict"))]
430    on_conflict: OnConflict,
431}
432
433impl NotNull {
434    pub fn new(on_conflict: OnConflict) -> Self {
435        Self {
436            on_conflict,
437        }
438    }
439
440    pub fn set_on_conflict(mut self, on_conf: OnConflict) -> Self {
441        self.on_conflict = on_conf;
442        self
443    }
444}
445
446impl SQLPart for NotNull {
447    fn part_len(&self) -> Result<usize> {
448        Ok(9 + self.on_conflict.part_len()?)
449    }
450
451    fn part_str(&self, sql: &mut String) -> Result<()> {
452        sql.push_str("NOT NULL ");
453        self.on_conflict.part_str(sql)?;
454        Ok(())
455    }
456
457    #[cfg(test)]
458    fn possibilities(_: bool) -> Vec<Box<Self>> {
459        let mut ret: Vec<Box<Self>> = Vec::new();
460        for conf in OnConflict::possibilities(false) {
461            ret.push(Box::new(Self::new(*conf)))
462        }
463        ret
464    }
465}
466
467// endregion
468
469// region Unique
470
471/// Marks a [Column] as "Unique", meaning the Column cannot contain the same value twice, and trying to insert a value for the second time is an Error.
472#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
473#[cfg_attr(feature = "xml-config", derive(Serialize, Deserialize))]
474pub struct Unique {
475    #[cfg_attr(feature = "xml-config", serde(default, rename = "@on_conflict"))]
476    on_conflict: OnConflict,
477}
478
479impl Unique {
480    pub fn new(on_conflict: OnConflict) -> Self {
481        Self {
482            on_conflict,
483        }
484    }
485
486    pub fn set_on_conflict(mut self, on_conf: OnConflict) -> Self {
487        self.on_conflict = on_conf;
488        self
489    }
490}
491
492impl SQLPart for Unique {
493    fn part_len(&self) -> Result<usize> {
494        Ok(7 + self.on_conflict.part_len()?)
495    }
496
497    fn part_str(&self, sql: &mut String) -> Result<()> {
498        sql.push_str("UNIQUE ");
499        self.on_conflict.part_str(sql)?;
500        Ok(())
501    }
502
503    #[cfg(test)]
504    fn possibilities(_: bool) -> Vec<Box<Self>> {
505        let mut ret: Vec<Box<Self>> = Vec::new();
506        for conf in OnConflict::possibilities(false) {
507            ret.push(Box::new(Self::new(*conf)))
508        }
509        ret
510    }
511}
512
513// endregion
514
515// region Foreign Key
516
517/// Defines a Foreign Key for a [Column]. It is an Error for the `foreign_table` and `foreign_column` [String]s to be Empty ([Error::EmptyForeignTableName], [Error::EmptyForeignColumnName]).
518#[derive(Debug, Clone, PartialEq, Eq)]
519#[cfg_attr(feature = "xml-config", derive(Serialize, Deserialize))]
520pub struct ForeignKey {
521    #[cfg_attr(feature = "xml-config", serde(rename = "@foreign_table"))]
522    foreign_table: String,
523    #[cfg_attr(feature = "xml-config", serde(rename = "@foreign_column"))]
524    foreign_column: String,
525    #[cfg_attr(feature = "xml-config", serde(rename = "@on_delete"))]
526    on_delete: Option<FKOnAction>,
527    #[cfg_attr(feature = "xml-config", serde(rename = "@on_update"))]
528    on_update: Option<FKOnAction>,
529    #[cfg_attr(feature = "xml-config", serde(rename = "@deferrable", default))]
530    deferrable: bool,
531}
532
533impl ForeignKey {
534    fn check(&self) -> Result<()> {
535        if self.foreign_table.is_empty() {
536            return Err(Error::EmptyForeignTableName);
537        }
538        if self.foreign_column.is_empty() {
539            return Err(Error::EmptyForeignColumnName);
540        }
541        Ok(())
542    }
543
544    pub fn new(foreign_table: String, foreign_column: String, on_delete: Option<FKOnAction>, on_update: Option<FKOnAction>, deferrable: bool) -> Self {
545        Self {
546            foreign_table,
547            foreign_column,
548            on_delete,
549            on_update,
550            deferrable,
551        }
552    }
553
554    pub fn new_default(foreign_table: String, foreign_column: String) -> Self {
555        Self {
556            foreign_table,
557            foreign_column,
558            on_delete: Default::default(),
559            on_update: Default::default(),
560            deferrable: Default::default(),
561        }
562    }
563
564    pub fn set_foreign_table(mut self, foreign_table: String) -> Self {
565        self.foreign_table = foreign_table;
566        self
567    }
568
569    pub fn set_foreign_column(mut self, foreign_column: String) -> Self {
570        self.foreign_column = foreign_column;
571        self
572    }
573
574    pub fn set_on_delete(mut self, on_delete: Option<FKOnAction>) -> Self {
575        self.on_delete = on_delete;
576        self
577    }
578
579    pub fn set_on_update(mut self, on_update: Option<FKOnAction>) -> Self {
580        self.on_update = on_update;
581        self
582    }
583
584    pub fn set_deferrable(mut self, deferrable: bool) -> Self {
585        self.deferrable = deferrable;
586        self
587    }
588}
589
590impl SQLPart for ForeignKey {
591    fn part_len(&self) -> Result<usize> {
592        self.check()?;
593
594        let on_del_len: usize = if let Some(on_del) = self.on_delete.as_ref() {
595            on_del.part_len()? + 1
596        } else {
597            0
598        };
599
600        let on_upd_len: usize = if let Some(on_upd) = self.on_update.as_ref() {
601            on_upd.part_len()? + 1
602        } else {
603            0
604        };
605
606        Ok(11 + self.foreign_table.len() + 2 + self.foreign_column.len() + 1 + on_del_len + on_upd_len + self.deferrable as usize * 30)
607    }
608
609    fn part_str(&self, sql: &mut String) -> Result<()> {
610        self.check()?;
611        sql.push_str("REFERENCES ");
612        sql.push_str(self.foreign_table.as_str());
613        sql.push_str(" (");
614        sql.push_str(self.foreign_column.as_str());
615        sql.push(')');
616
617        if let Some(on_del) = self.on_delete.as_ref() {
618            sql.push(' ');
619            on_del.part_str(sql)?;
620        }
621
622        if let Some(on_upd) = self.on_update.as_ref() {
623            sql.push(' ');
624            on_upd.part_str(sql)?;
625        }
626
627        if self.deferrable {
628            sql.push_str(" DEFERRABLE INITIALLY DEFERRED");
629        }
630
631        Ok(())
632    }
633
634    #[cfg(test)]
635    fn possibilities(illegal: bool) -> Vec<Box<Self>> {
636        let mut ret: Vec<Box<Self>> = Vec::new();
637        for tbl in [if illegal { "".to_string() } else { "test".to_string() }, "test".to_string()] {
638            for col in [if illegal { "".to_string() } else { "test".to_string() }, "test".to_string()] {
639                for on_del in option_iter(FKOnAction::possibilities(false)) {
640                    for on_upd in option_iter(FKOnAction::possibilities(false)) {
641                        for defer in [true, false] {
642                            ret.push(Box::new(Self::new(tbl.clone(), col.clone(), on_del, on_upd, defer)));
643                        }
644                    }
645                }
646            }
647        }
648        ret
649    }
650}
651
652// endregion
653
654// region Generated
655
656/// Defines a [Column] as Generated. It is an Error for the `expr` [String] to be Empty ([Error::EmptyGeneratorExpr])
657#[derive(Debug, Clone, PartialEq, Eq)]
658#[cfg_attr(feature = "xml-config", derive(Serialize, Deserialize))]
659pub struct Generated {
660    #[cfg_attr(feature = "xml-config", serde(rename = "@expr"))]
661    expr: String,
662    #[cfg_attr(feature = "xml-config", serde(rename = "@as"))]
663    generated_as: Option<GeneratedAs>,
664}
665
666impl Generated {
667    fn check(&self) -> Result<()> {
668        if self.expr.is_empty() {
669            return Err(Error::EmptyGeneratorExpr);
670        }
671        Ok(())
672    }
673
674    pub fn new(expr: String, generated_as: Option<GeneratedAs>) -> Self {
675        Self {
676            expr,
677            generated_as,
678        }
679    }
680
681    pub fn new_default(expr: String) -> Self {
682        Self {
683            expr,
684            generated_as: Default::default(),
685        }
686    }
687
688    pub fn set_expr(mut self, expr: String) -> Self {
689        self.expr = expr;
690        self
691    }
692
693    pub fn set_generated_as(mut self, generated_as: Option<GeneratedAs>) -> Self {
694        self.generated_as = generated_as;
695        self
696    }
697}
698
699impl SQLPart for Generated {
700    fn part_len(&self) -> Result<usize> {
701        self.check()?;
702
703        let generated_as_len: usize = if let Some(generated_as) = self.generated_as.as_ref() {
704            generated_as.part_len()? + 1
705        } else {
706            0
707        };
708
709        Ok(21 + self.expr.len() + 1 + generated_as_len)
710    }
711
712    fn part_str(&self, sql: &mut String) -> Result<()> {
713        self.check()?;
714
715        sql.push_str("GENERATED ALWAYS AS (");
716        sql.push_str(self.expr.as_str());
717        sql.push(')');
718        if let Some(generated_as) = self.generated_as.as_ref() {
719            sql.push(' ');
720            generated_as.part_str(sql)?;
721        }
722
723        Ok(())
724    }
725
726    #[cfg(test)]
727    fn possibilities(illegal: bool) -> Vec<Box<Self>> {
728        let mut ret: Vec<Box<Self>> = Vec::new();
729        for expr in [if illegal { "".to_string() } else { "test".to_string() }, "test".to_string()] {
730            for gen_as in option_iter(GeneratedAs::possibilities(false)) {
731                ret.push(Box::new(Self::new(expr.clone(), gen_as)));
732            }
733        }
734        ret
735    }
736}
737
738// endregion
739
740// region Column
741
742/// This struct Represents a Column in a [Table]. It is an Error for the `name` to be Empty ([Error::EmptyColumnName]).
743#[derive(Debug, Clone, PartialEq, Eq)]
744#[cfg_attr(feature = "xml-config", derive(Serialize, Deserialize))]
745pub struct Column {
746    #[cfg_attr(feature = "xml-config", serde(rename = "@type"))]
747    typ: SQLiteType,
748    #[cfg_attr(feature = "xml-config", serde(rename = "@name"))]
749    name: String,
750    #[cfg_attr(feature = "xml-config", serde(skip_serializing_if = "Option::is_none"))]
751    pk: Option<PrimaryKey>,
752    #[cfg_attr(feature = "xml-config", serde(skip_serializing_if = "Option::is_none"))]
753    unique: Option<Unique>,
754    #[cfg_attr(feature = "xml-config", serde(skip_serializing_if = "Option::is_none"))]
755    fk: Option<ForeignKey>,
756    #[cfg_attr(feature = "xml-config", serde(skip_serializing_if = "Option::is_none"))]
757    not_null: Option<NotNull>,
758    #[cfg_attr(feature = "xml-config", serde(skip_serializing_if = "Option::is_none"))]
759    generated: Option<Generated>,
760}
761
762impl Column {
763    fn check(&self) -> Result<()> {
764        if self.name.is_empty() {
765            return Err(Error::EmptyColumnName);
766        }
767
768        if self.pk.is_some() && self.fk.is_some() {
769            return Err(Error::PrimaryKeyAndForeignKey);
770        }
771
772        if self.pk.is_some() && self.unique.is_some() {
773            return Err(Error::PrimaryKeyAndUnique);
774        }
775
776        Ok(())
777    }
778
779    pub fn new(typ: SQLiteType, name: String, pk: Option<PrimaryKey>, unique: Option<Unique>, fk: Option<ForeignKey>, not_null: Option<NotNull>, generated: Option<Generated>) -> Self {
780        Self {
781            typ,
782            name,
783            pk,
784            unique,
785            fk,
786            not_null,
787            generated,
788        }
789    }
790
791    pub fn new_default(name: String) -> Self {
792        Self {
793            typ: Default::default(),
794            name,
795            pk: Default::default(),
796            unique: Default::default(),
797            fk: Default::default(),
798            not_null: Default::default(),
799            generated: Default::default(),
800        }
801    }
802
803    pub fn new_typed(typ: SQLiteType, name: String) -> Self {
804        Self {
805            typ,
806            name,
807            pk: Default::default(),
808            unique: Default::default(),
809            fk: Default::default(),
810            not_null: Default::default(),
811            generated: Default::default(),
812        }
813    }
814
815    pub fn set_type(mut self, typ: SQLiteType) -> Self {
816        self.typ = typ;
817        self
818    }
819
820    pub fn set_name(mut self, name: String) -> Self {
821        self.name = name;
822        self
823    }
824
825    pub fn set_pk(mut self, pk: Option<PrimaryKey>) -> Self {
826        self.pk = pk;
827        self
828    }
829
830    pub fn set_unique(mut self, unique: Option<Unique>) -> Self {
831        self.unique = unique;
832        self
833    }
834
835    pub fn set_fk(mut self, fk: Option<ForeignKey>) -> Self {
836        self.fk = fk;
837        self
838    }
839}
840
841impl SQLPart for Column {
842    fn part_len(&self) -> Result<usize> {
843        self.check()?;
844        let pk_len: usize = if let Some(pk) = self.pk.as_ref() {
845            pk.part_len()? + 1
846        } else {
847            0
848        };
849
850        let unique_len: usize = if let Some(unique) = self.unique.as_ref() {
851            unique.part_len()? + 1
852        } else {
853            0
854        };
855
856        let fk_len: usize = if let Some(fk) = self.fk.as_ref() {
857            fk.part_len()? + 1
858        } else {
859            0
860        };
861
862        Ok(self.name.len() + 1 + self.typ.part_len()? + pk_len + unique_len + fk_len)
863    }
864
865    fn part_str(&self, sql: &mut String) -> Result<()> {
866        self.check()?;
867        sql.push_str(self.name.as_str());
868        sql.push(' ');
869        self.typ.part_str(sql)?;
870
871        if let Some(pk) = self.pk.as_ref() {
872            sql.push(' ');
873            pk.part_str(sql)?;
874        }
875
876        if let Some(unique) = self.unique.as_ref() {
877            sql.push(' ');
878            unique.part_str(sql)?;
879        }
880
881        if let Some(fk) = self.fk.as_ref() {
882            sql.push(' ');
883            fk.part_str(sql)?;
884        }
885        Ok(())
886    }
887
888    #[cfg(test)]
889    fn possibilities(illegal: bool) -> Vec<Box<Self>> {
890        let mut ret: Vec<Box<Self>> = Vec::new();
891        for typ in SQLiteType::possibilities(false) {
892            for name in [if illegal { "".to_string() } else { "test".to_string() }, "test".to_string()] {
893                for pk in option_iter(PrimaryKey::possibilities(false)) {
894                    for unique in option_iter(Unique::possibilities(false)) {
895                        for fk in option_iter(ForeignKey::possibilities(illegal)) {
896                            for nn in option_iter(NotNull::possibilities(false)) {
897                                for gened in option_iter(Generated::possibilities(illegal)) {
898                                    if !illegal && pk.is_some() && (fk.is_some() || unique.is_some()) {
899                                        continue;
900                                    }
901                                    ret.push(Box::new(Self::new(*typ.clone(), name.clone(), pk.clone(), unique, fk.clone(), nn, gened)));
902                                }
903                            }
904                        }
905                    }
906                }
907            }
908        }
909        ret
910    }
911}
912
913// endregion
914
915// region ViewColumn
916
917#[derive(Debug, Clone, PartialEq, Eq)]
918#[cfg_attr(feature = "xml-config", derive(Serialize, Deserialize))]
919pub struct ViewColumn {
920    #[cfg_attr(feature = "xml-config", serde(rename = "@name"))]
921    name: String,
922}
923
924impl ViewColumn {
925    pub fn new(name: String) -> Self {
926        Self {
927            name,
928        }
929    }
930
931    pub fn set_name(mut self, name: String) {
932        self.name = name;
933    }
934}
935
936impl SQLPart for ViewColumn {
937    fn part_len(&self) -> Result<usize> {
938        Ok(self.name.len())
939    }
940
941    fn part_str(&self, sql: &mut String) -> Result<()> {
942        sql.push_str(self.name.as_str());
943        Ok(())
944    }
945
946    #[cfg(test)]
947    fn possibilities(_illegal_variants: bool) -> Vec<Box<Self>> {
948        let mut ret: Vec<Box<Self>> = Vec::new();
949        ret.push(Box::new(ViewColumn::new("test".to_string())));
950        ret
951    }
952}
953
954// endregion
955
956// region View
957
958/// Represents an entire View, which may be Part of a wider [Schema] or used standalone.
959/// Can be converted into an SQL Statement via the [SQLStatement] Methods.
960/// It is an Error for the `name` to be empty ([Error::EmptyViewName]) or the Select to be empty ([Error::EmptyViewSelect]).
961#[derive(Debug, Clone, Eq)]
962#[cfg_attr(feature = "xml-config", derive(Serialize, Deserialize), serde(rename = "view"))]
963pub struct View {
964    #[cfg_attr(feature = "xml-config", serde(rename = "@name"))]
965    name: String,
966    #[cfg_attr(feature = "xml-config", serde(rename = "@temp", default))]
967    temp: bool,
968    #[cfg_attr(feature = "xml-config", serde(rename = "column"))]
969    columns: Vec<ViewColumn>,
970    #[cfg_attr(feature = "xml-config", serde(rename = "@select"))]
971    select: String,
972    #[cfg_attr(feature = "xml-config", serde(skip))]
973    pub(crate) if_exists: bool,
974}
975
976impl View {
977    fn check(&self) -> Result<()> {
978        if self.name.is_empty() {
979            return Err(Error::EmptyViewName);
980        }
981        if self.select.is_empty() {
982            return Err(Error::EmptyViewSelect);
983        }
984        Ok(())
985    }
986
987    pub fn new(name: String, temp: bool, columns: Vec<ViewColumn>, select: String) -> Self {
988        Self {
989            name,
990            temp,
991            columns,
992            select,
993            if_exists: false,
994        }
995    }
996
997    pub fn new_default(name: String, select: String) -> Self {
998        Self {
999            name,
1000            temp: Default::default(),
1001            columns: Default::default(),
1002            select,
1003            if_exists: Default::default(),
1004        }
1005    }
1006
1007    pub fn add_column(mut self, column: ViewColumn) -> Self {
1008        self.columns.push(column);
1009        self
1010    }
1011
1012    pub fn set_name(mut self, name: String) -> Self {
1013        self.name = name;
1014        self
1015    }
1016
1017    pub fn set_temp(mut self, temp: bool) -> Self {
1018        self.temp = temp;
1019        self
1020    }
1021
1022    pub fn set_select(mut self, select: String) -> Self {
1023        self.select = select;
1024        self
1025    }
1026}
1027
1028impl SQLPart for View {
1029    fn part_len(&self) -> Result<usize> {
1030        self.check()?;
1031        let pre_coll: usize = 7 // "CREATE "
1032            + self.temp as usize * 10 // "TEMPORARY "
1033            + 5 // "VIEW "
1034            + self.if_exists as usize * 14 // "IF NOT EXISTS "
1035            + self.name.len()
1036            + 2; // " ("
1037
1038        let post_coll: usize = 5 // ") AS "
1039            + self.select.len();
1040
1041        if self.columns.is_empty() {
1042            return Err(Error::NoColumns);
1043        }
1044        let coll: usize = {
1045            let mut cnt: usize = 0;
1046            for coll in self.columns.iter() {
1047                cnt += 2; // " ,"
1048                cnt += coll.part_len()?;
1049            }
1050            cnt - 2 // remove last " ,"
1051        };
1052        Ok(pre_coll + coll + post_coll)
1053    }
1054
1055    fn part_str(&self, sql: &mut String) -> Result<()> {
1056        self.check()?;
1057
1058        sql.push_str("CREATE ");
1059        if self.temp {
1060            sql.push_str("TEMPORARY ");
1061        }
1062        sql.push_str("VIEW ");
1063        if self.if_exists {
1064            sql.push_str("IF NOT EXISTS ");
1065        }
1066        sql.push_str(&self.name);
1067        if !self.columns.is_empty() {
1068            sql.push_str(" (");
1069            let mut first: bool = true;
1070            for coll in self.columns.iter() {
1071                if !first {
1072                    sql.push_str(", ");
1073                } else {
1074                    first = false;
1075                }
1076                coll.part_str(sql)?;
1077            }
1078            sql.push(')');
1079        }
1080        sql.push_str(" AS ");
1081        sql.push_str(&self.select);
1082
1083        Ok(())
1084    }
1085
1086    #[cfg(test)]
1087    fn possibilities(illegal: bool) -> Vec<Box<Self>> {
1088        let mut ret: Vec<Box<Self>> = Vec::new();
1089        for name in [if illegal { "".to_string() } else { "test".to_string() }, "test".to_string()] {
1090            for select in [if illegal { "".to_string() } else { "test".to_string() }, "test".to_string()] {
1091                for temp in [true, false] {
1092                    for col_num in [if illegal { 0 } else { 3 }, 1, 2] {
1093                        let mut cols: Vec<ViewColumn> = Vec::new();
1094                        for n in 0..col_num {
1095                            cols.push(ViewColumn::new(format!("test{}", n)))
1096                            // todo not all column possibilities
1097                        }
1098                        ret.push(Box::new(View::new(name.clone(), temp, cols, select.clone())));
1099                    }
1100                }
1101            }
1102        }
1103        ret
1104    }
1105}
1106
1107impl SQLStatement for View {
1108    fn len(&mut self, transaction: bool, if_exists: bool) -> Result<usize> {
1109        self.if_exists = if_exists;
1110        Ok(transaction as usize * 7 + self.part_len()? + 1 + transaction as usize * 5)
1111    }
1112
1113    fn build(&mut self, transaction: bool, if_exists: bool) -> Result<String> {
1114        let mut str = String::with_capacity(self.len(transaction, if_exists)?);
1115        if transaction {
1116            str.push_str("BEGIN;\n");
1117        }
1118        self.part_str(&mut str)?;
1119        str.push(';');
1120        if transaction {
1121            str.push_str("\nEND;");
1122        }
1123        Ok(str)
1124    }
1125
1126    #[cfg(feature = "rusqlite")]
1127    fn check_db(&mut self, _conn: &Connection) -> Result<Option<String>, CheckError> {
1128        todo!()
1129    }
1130
1131    #[cfg(all(test, feature = "xml-config"))]
1132    fn to_any(self) -> AnySql {
1133        AnySql::View(self)
1134    }
1135}
1136
1137impl PartialEq<Self> for View {
1138    fn eq(&self, other: &Self) -> bool {
1139        if self.name != other.name || self.temp != other.temp || self.select != other.select {
1140            return false;
1141        }
1142        for columns in self.columns.iter().zip(other.columns.iter()) {
1143            if columns.0 != columns.1 {
1144                return false;
1145            }
1146        }
1147        true
1148    }
1149}
1150
1151// endregion
1152
1153// region Table
1154
1155/// Represents an entire Table, which may be Part of a wider [Schema] or used standalone.
1156/// Can be converted into an SQL Statement via the [SQLStatement] Methods.
1157/// It is an Error for the `name` to be empty ([Error::EmptyTableName]) or the Table itself to be empty ([Error::NoColumns]).
1158#[derive(Debug, Clone, Eq)]
1159#[cfg_attr(feature = "xml-config", derive(Serialize, Deserialize), serde(rename = "table"))]
1160pub struct Table {
1161    #[cfg_attr(feature = "xml-config", serde(rename = "@name"))]
1162    name: String,
1163    #[cfg_attr(feature = "xml-config", serde(rename = "column"))]
1164    columns: Vec<Column>,
1165    #[cfg_attr(feature = "xml-config", serde(rename = "@without_rowid", default))]
1166    without_rowid: bool,
1167    #[cfg_attr(feature = "xml-config", serde(rename = "@strict", default))]
1168    strict: bool,
1169    #[cfg_attr(feature = "xml-config", serde(skip))]
1170    pub(crate) if_exists: bool,
1171}
1172
1173impl Table {
1174    fn check(&self) -> Result<()> {
1175        let mut has_pk: bool = false;
1176        for col in &self.columns {
1177            if col.pk.is_some() {
1178                if has_pk {
1179                    return Err(Error::MultiplePrimaryKeys);
1180                } else {
1181                    has_pk = true;
1182                }
1183            }
1184        }
1185
1186        if self.name.is_empty() {
1187            return Err(Error::EmptyTableName);
1188        }
1189
1190        if self.columns.is_empty() {
1191            return Err(Error::NoColumns);
1192        }
1193
1194        if self.without_rowid && !has_pk {
1195            return Err(Error::WithoutRowidNoPrimaryKey);
1196        }
1197        Ok(())
1198    }
1199
1200    pub fn new(name: String, columns: Vec<Column>, without_rowid: bool, strict: bool) -> Self {
1201        Self {
1202            name,
1203            columns,
1204            without_rowid,
1205            strict,
1206            if_exists: false,
1207        }
1208    }
1209
1210    pub fn new_default(name: String) -> Self {
1211        Self {
1212            name,
1213            columns: Vec::new(),
1214            without_rowid: Default::default(),
1215            strict: Default::default(),
1216            if_exists: Default::default(),
1217        }
1218    }
1219
1220    pub fn set_name(mut self, name: String) -> Self {
1221        self.name = name;
1222        self
1223    }
1224
1225    pub fn add_column(mut self, col: Column) -> Self {
1226        self.columns.push(col);
1227        self
1228    }
1229
1230    pub fn set_without_rowid(mut self, without_rowid: bool) -> Self {
1231        self.without_rowid = without_rowid;
1232        self
1233    }
1234
1235    pub fn set_strict(mut self, strict: bool) -> Self {
1236        self.strict = strict;
1237        self
1238    }
1239}
1240
1241impl SQLPart for Table {
1242    fn part_len(&self) -> Result<usize> {
1243        self.check()?;
1244        let mut cols_len: usize = 0;
1245        for col in &self.columns {
1246            cols_len += col.part_len()?;
1247        }
1248        Ok(
1249            13  // "CREATE TABLE "
1250                + self.if_exists as usize * 14 // "IF NOT EXISTS "
1251                + self.name.len()
1252                + 2 // " ("
1253                + cols_len
1254                + self.columns.len() - 1 // commas for cols, -1 b/c the last doesn't have a comma
1255                + 1 // ')'
1256                + self.without_rowid as usize * 14 // " WITHOUT ROWID"
1257                + ((self.without_rowid && self.strict) as usize) // ','
1258                + self.strict as usize * 7 // " STRICT"
1259        )
1260    }
1261
1262    fn part_str(&self, sql: &mut String) -> Result<()> {
1263        self.check()?;
1264
1265        sql.push_str("CREATE TABLE ");
1266        if self.if_exists {
1267            sql.push_str("IF NOT EXISTS ");
1268        }
1269        sql.push_str(self.name.as_str());
1270        sql.push_str(" (");
1271
1272        let mut needs_comma = false;
1273        for coll in &self.columns {
1274            if needs_comma {
1275                sql.push(',');
1276            }
1277            coll.part_str(sql)?;
1278            needs_comma = true;
1279        }
1280        sql.push(')');
1281
1282
1283        if self.without_rowid {
1284            sql.push_str(" WITHOUT ROWID");
1285        }
1286        if self.without_rowid && self.strict {
1287            sql.push(',');
1288        }
1289        if self.strict {
1290            sql.push_str(" STRICT");
1291        }
1292        Ok(())
1293    }
1294
1295    #[cfg(test)]
1296    fn possibilities(illegal: bool) -> Vec<Box<Self>> {
1297        let mut ret: Vec<Box<Self>> = Vec::new();
1298        for name in [if illegal { "".to_string() } else { "test".to_string() }, "test".to_string()] {
1299            for wo_rowid in [true, false] {
1300                for col_num in [if illegal { 0 } else { 3 }, 1, 2] {
1301                    let mut cols: Vec<Column> = Vec::new();
1302                    for n in 0..col_num {
1303                        cols.push(Column::new_default(format!("test{}", n)))
1304                        // todo not all column possibilities
1305                    }
1306                    if !illegal && wo_rowid {
1307                        cols[0].pk = Some(Default::default());
1308                    }
1309
1310                    for strict in [true, false] {
1311                        ret.push(Box::new(Self::new(name.clone(), cols.clone(), wo_rowid, strict)));
1312                    }
1313                }
1314            }
1315        }
1316        ret
1317    }
1318}
1319
1320#[cfg(feature = "rusqlite")]
1321fn check_table(ret: &mut String, num: usize, tbl: &Table, row: &Row) -> Result<(), CheckError> {
1322    if tbl.name != row.get::<&str, String>("name")? {
1323        write!(ret, "Table {}: expected name '{}', got '{}'; ", num, tbl.name, row.get::<&str, String>("name")?)?;
1324    }
1325    if tbl.without_rowid != row.get::<&str, bool>("wr")? {
1326        write!(ret, "Table {}: expected without_rowid {}, got {}; ", num, tbl.without_rowid, row.get::<&str, bool>("wr")?)?;
1327    }
1328    if tbl.strict != row.get::<&str, bool>("strict")? {
1329        write!(ret, "Table {}: expected strict {}, got {}; ", num, tbl.strict, row.get::<&str, bool>("strict")?)?;
1330    }
1331    if tbl.columns.len() != row.get::<&str, usize>("ncol")? {
1332        write!(ret, "Table {}: expected number of columns {}, got {}; ", num, tbl.columns.len(), row.get::<&str, usize>("ncol")?)?;
1333    }
1334    Ok(())
1335}
1336
1337impl SQLStatement for Table {
1338    fn len(&mut self, transaction: bool, if_exists: bool) -> Result<usize> {
1339        self.if_exists = if_exists;
1340        Ok(transaction as usize * 7 + self.part_len()? + 1 + transaction as usize * 5)
1341    }
1342
1343    fn build(&mut self, transaction: bool, if_exists: bool) -> Result<String> {
1344        let mut str = String::with_capacity(self.len(transaction, if_exists)?);
1345        if transaction {
1346            str.push_str("BEGIN;\n");
1347        }
1348        self.part_str(&mut str)?;
1349        str.push(';');
1350        if transaction {
1351            str.push_str("\nEND;");
1352        }
1353        Ok(str)
1354    }
1355
1356    #[cfg(feature = "rusqlite")]
1357    fn check_db(&mut self, conn: &Connection) -> Result<Option<String>, CheckError> {
1358        let mut ret: String = String::new();
1359
1360        let mut stmt: Statement = conn.prepare(r#"SELECT name, ncol, wr, strict FROM pragma_table_list() WHERE (schema == "main") AND (type == "table") AND (name == ?1);"#)?;
1361        let mut rows: Rows = stmt.query([&self.name])?;
1362
1363        if let Some(row) = rows.next()? {
1364            check_table(&mut ret, 1, self, row)?;
1365        } else {
1366            write!(ret, "Could not find table '{}'", self.name)?;
1367        }
1368
1369        if let Some(_) = rows.next()? {
1370            write!(ret, "Found two Tables with the name '{}'", self.name)?;
1371        }
1372
1373        if ret.is_empty() {
1374            Ok(None)
1375        } else {
1376            Ok(Some(ret))
1377        }
1378    }
1379
1380    #[cfg(all(test, feature = "xml-config"))]
1381    fn to_any(self) -> AnySql {
1382        AnySql::Table(self)
1383    }
1384}
1385
1386impl PartialEq<Self> for Table {
1387    fn eq(&self, other: &Self) -> bool {
1388        if self.name != other.name {
1389            return false;
1390        }
1391        if self.without_rowid != other.without_rowid {
1392            return false;
1393        }
1394        if self.strict != other.strict {
1395            return false;
1396        }
1397        if self.columns.len() != other.columns.len() {
1398            return false;
1399        }
1400        for columns in self.columns.iter().zip(other.columns.iter()) {
1401            if columns.0 != columns.1 {
1402                return false;
1403            }
1404        }
1405        true
1406    }
1407}
1408
1409// endregion
1410
1411// region Schema
1412
1413/// A Schema (or Layout, hence the crate name) encompasses one or more [Table]s.
1414/// Can be converted into an SQL Statement via the [SQLStatement] Methods.
1415/// It is an Error for the Schema to be empty ([Error::SchemaWithoutTables]).
1416#[derive(Debug, Clone, Default, Eq)]
1417#[cfg_attr(feature = "xml-config", derive(Serialize, Deserialize), serde(rename = "schema"))]
1418pub struct Schema {
1419    #[cfg_attr(feature = "xml-config", serde(rename = "table"), serde(default))]
1420    tables: Vec<Table>,
1421    #[cfg_attr(feature = "xml-config", serde(rename = "view"), serde(default))]
1422    views: Vec<View>,
1423}
1424
1425impl Schema {
1426    fn check(&self) -> Result<()> {
1427        if self.tables.is_empty() {
1428            return Err(Error::EmptySchema);
1429        }
1430        Ok(())
1431    }
1432
1433    pub fn new() -> Self {
1434        Self {
1435            tables: Vec::new(),
1436            views: Vec::new(),
1437        }
1438    }
1439
1440    pub fn add_table(mut self, new_table: Table) -> Self {
1441        self.tables.push(new_table);
1442        self
1443    }
1444
1445    pub fn add_view(mut self, new_view: View) -> Self {
1446        self.views.push(new_view);
1447        self
1448    }
1449}
1450
1451impl SQLStatement for Schema {
1452    fn len(&mut self, transaction: bool, if_exists: bool) -> Result<usize> {
1453        self.check()?;
1454        let mut tables_len: usize = 0;
1455        for tbl in &mut self.tables {
1456            tbl.if_exists = if_exists;
1457            tables_len += tbl.part_len()?;
1458        }
1459        let mut views_len: usize = 0;
1460        for view in &mut self.views {
1461            view.if_exists = if_exists;
1462            views_len += view.part_len()?;
1463        }
1464        Ok(transaction as usize * 7 + tables_len + self.tables.len() + views_len + self.views.len() + transaction as usize * 5)
1465    }
1466
1467    fn build(&mut self, transaction: bool, if_exists: bool) -> Result<String> {
1468        self.check()?;
1469        let mut ret: String = String::with_capacity(self.len(transaction, if_exists)?);
1470        if transaction {
1471            ret.push_str("BEGIN;\n");
1472        }
1473
1474        for tbl in &self.tables {
1475            tbl.part_str(&mut ret)?;
1476            ret.push(';');
1477        }
1478
1479        if transaction {
1480            ret.push_str("\nEND;")
1481        }
1482        Ok(ret)
1483    }
1484
1485    #[cfg(feature = "rusqlite")]
1486    fn check_db(&mut self, conn: &Connection) -> Result<Option<String>, CheckError> {
1487        self.tables.sort_unstable_by_key(|table: &Table| table.name.clone()); // todo ugly :(
1488
1489        let mut ret: String = String::new();
1490
1491        let mut stmt: Statement = conn.prepare(r#"SELECT name, ncol, wr, strict FROM pragma_table_list() WHERE (schema == "main") AND (type == "table") AND name NOT LIKE "%schema" ORDER BY name;"#)?;
1492        let mut rows: Rows = stmt.query(())?;
1493
1494
1495        for (num, table) in self.tables.iter().enumerate() {
1496            let row: &Row = {
1497                let raw_row = rows.next()?;
1498                match raw_row {
1499                    None => {
1500                        write!(ret, "Table {}: expected table '{}', got nothing; ", num, table.name)?;
1501                        break;
1502                    }
1503                    Some(row) => { row }
1504                }
1505            };
1506            check_table(&mut ret, num, table, row)?;
1507        }
1508
1509        let mut i: usize = self.tables.len();
1510        while let Some(row) = rows.next()? {
1511            write!(ret, "Table {}: expected nothing, got table '{}'; ", i, row.get::<&str, String>("name")?)?;
1512            i += 1;
1513        }
1514
1515        if ret.is_empty() {
1516            Ok(None)
1517        } else {
1518            Ok(Some(ret))
1519        }
1520    }
1521
1522    #[cfg(all(test, feature = "xml-config"))]
1523    fn to_any(self) -> AnySql {
1524        AnySql::Schema(self)
1525    }
1526}
1527
1528impl PartialEq<Schema> for Schema {
1529    fn eq(&self, other: &Schema) -> bool {
1530        if self.tables.len() != other.tables.len() {
1531            return false;
1532        }
1533        for tables in self.tables.iter().zip(other.tables.iter()) {
1534            if tables.0 != tables.1 {
1535                return false;
1536            }
1537        }
1538        true
1539    }
1540}
1541
1542// endregion Schema
1543
1544#[cfg(test)]
1545mod tests {
1546    use super::*;
1547    use anyhow::Result;
1548
1549    #[cfg(feature = "rusqlite")]
1550    fn test_sql<S: SQLStatement>(stmt: &mut S) -> Result<()> {
1551        for if_exists in [true, false] {
1552            for transaction in [true, false] {
1553                let sql: String = stmt.build(transaction, if_exists)?;
1554
1555                assert_eq!(sql.len(), stmt.len(transaction, if_exists)?);
1556
1557                let conn: Connection = Connection::open_in_memory()?;
1558                let ret = conn.execute_batch(&sql);
1559                if ret.is_err() {
1560                    println!("Error SQL: '{}'", sql)
1561                }
1562                ret?
1563            }
1564        }
1565
1566        Ok(())
1567    }
1568
1569    #[cfg(not(feature = "rusqlite"))]
1570    fn test_sql<S: SQLStatement>(_stmt: &mut S) -> Result<()> {
1571        // todo ???
1572        Ok(())
1573    }
1574
1575    fn test_sql_part<P: SQLPart>(part: &P) -> Result<()> {
1576        let mut str: String = String::with_capacity(part.part_len()?);
1577
1578        part.part_str(&mut str)?;
1579        assert_eq!(str.len(), part.part_len()?);
1580
1581        Ok(())
1582    }
1583
1584    #[test]
1585    fn test_sqlite_type() -> Result<()> {
1586        let mut str: String;
1587
1588        str = String::new();
1589        SQLiteType::Blob.part_str(&mut str)?;
1590        assert_eq!(str, "BLOB");
1591        assert_eq!(str.len(), SQLiteType::Blob.part_len()?);
1592
1593        str = String::new();
1594        SQLiteType::Numeric.part_str(&mut str)?;
1595        assert_eq!(str, "NUMERIC");
1596        assert_eq!(str.len(), SQLiteType::Numeric.part_len()?);
1597
1598        str = String::new();
1599        SQLiteType::Integer.part_str(&mut str)?;
1600        assert_eq!(str, "INTEGER");
1601        assert_eq!(str.len(), SQLiteType::Integer.part_len()?);
1602
1603        str = String::new();
1604        SQLiteType::Real.part_str(&mut str)?;
1605        assert_eq!(str, "REAL");
1606        assert_eq!(str.len(), SQLiteType::Real.part_len()?);
1607
1608        str = String::new();
1609        SQLiteType::Text.part_str(&mut str)?;
1610        assert_eq!(str, "TEXT");
1611        assert_eq!(str.len(), SQLiteType::Text.part_len()?);
1612
1613        Ok(())
1614    }
1615
1616    #[test]
1617    fn test_order() -> Result<()> {
1618        let mut str: String;
1619
1620        str = String::new();
1621        Order::Ascending.part_str(&mut str)?;
1622        assert_eq!(str, "ASC");
1623        assert_eq!(str.len(), Order::Ascending.part_len()?);
1624
1625        str = String::new();
1626        Order::Descending.part_str(&mut str)?;
1627        assert_eq!(str, "DESC");
1628        assert_eq!(str.len(), Order::Descending.part_len()?);
1629
1630        Ok(())
1631    }
1632
1633    #[test]
1634    fn test_on_conflict() -> Result<()> {
1635        let mut str: String;
1636
1637        str = String::new();
1638        OnConflict::Rollback.part_str(&mut str)?;
1639        assert_eq!(str, "ON CONFLICT ROLLBACK");
1640        assert_eq!(str.len(), OnConflict::Rollback.part_len()?);
1641
1642        str = String::new();
1643        OnConflict::Abort.part_str(&mut str)?;
1644        assert_eq!(str, "ON CONFLICT ABORT");
1645        assert_eq!(str.len(), OnConflict::Abort.part_len()?);
1646
1647        str = String::new();
1648        OnConflict::Fail.part_str(&mut str)?;
1649        assert_eq!(str, "ON CONFLICT FAIL");
1650        assert_eq!(str.len(), OnConflict::Fail.part_len()?);
1651
1652        str = String::new();
1653        OnConflict::Ignore.part_str(&mut str)?;
1654        assert_eq!(str, "ON CONFLICT IGNORE");
1655        assert_eq!(str.len(), OnConflict::Ignore.part_len()?);
1656
1657        str = String::new();
1658        OnConflict::Replace.part_str(&mut str)?;
1659        assert_eq!(str, "ON CONFLICT REPLACE");
1660        assert_eq!(str.len(), OnConflict::Replace.part_len()?);
1661
1662        Ok(())
1663    }
1664
1665    #[test]
1666    fn test_fk_on_action() -> Result<()> {
1667        let mut str: String;
1668
1669        str = String::new();
1670        FKOnAction::SetNull.part_str(&mut str)?;
1671        assert_eq!(str, "SET NULL");
1672        assert_eq!(str.len(), FKOnAction::SetNull.part_len()?);
1673
1674        str = String::new();
1675        FKOnAction::SetDefault.part_str(&mut str)?;
1676        assert_eq!(str, "SET DEFAULT");
1677        assert_eq!(str.len(), FKOnAction::SetDefault.part_len()?);
1678
1679        str = String::new();
1680        FKOnAction::Cascade.part_str(&mut str)?;
1681        assert_eq!(str, "CASCADE");
1682        assert_eq!(str.len(), FKOnAction::Cascade.part_len()?);
1683
1684        str = String::new();
1685        FKOnAction::Restrict.part_str(&mut str)?;
1686        assert_eq!(str, "RESTRICT");
1687        assert_eq!(str.len(), FKOnAction::Restrict.part_len()?);
1688
1689        str = String::new();
1690        FKOnAction::NoAction.part_str(&mut str)?;
1691        assert_eq!(str, "NO ACTION");
1692        assert_eq!(str.len(), FKOnAction::NoAction.part_len()?);
1693
1694        Ok(())
1695    }
1696
1697    #[test]
1698    fn test_generated_as() -> Result<()> {
1699        let mut str: String;
1700
1701        str = String::new();
1702        GeneratedAs::Virtual.part_str(&mut str)?;
1703        assert_eq!(str, "VIRTUAL");
1704        assert_eq!(str.len(), GeneratedAs::Virtual.part_len()?);
1705
1706        str = String::new();
1707        GeneratedAs::Stored.part_str(&mut str)?;
1708        assert_eq!(str, "STORED");
1709        assert_eq!(str.len(), GeneratedAs::Stored.part_len()?);
1710
1711        Ok(())
1712    }
1713
1714    #[test]
1715    fn test_not_null() -> Result<()> {
1716        let mut str: String;
1717
1718        str = String::new();
1719        NotNull::new(OnConflict::Rollback).part_str(&mut str)?;
1720        assert_eq!(str, "NOT NULL ON CONFLICT ROLLBACK");
1721        assert_eq!(str.len(), NotNull::new(OnConflict::Rollback).part_len()?);
1722
1723        str = String::new();
1724        NotNull::new(OnConflict::Abort).part_str(&mut str)?;
1725        assert_eq!(str, "NOT NULL ON CONFLICT ABORT");
1726        assert_eq!(str.len(), NotNull::new(OnConflict::Abort).part_len()?);
1727
1728        str = String::new();
1729        NotNull::new(OnConflict::Fail).part_str(&mut str)?;
1730        assert_eq!(str, "NOT NULL ON CONFLICT FAIL");
1731        assert_eq!(str.len(), NotNull::new(OnConflict::Fail).part_len()?);
1732
1733        str = String::new();
1734        NotNull::new(OnConflict::Ignore).part_str(&mut str)?;
1735        assert_eq!(str, "NOT NULL ON CONFLICT IGNORE");
1736        assert_eq!(str.len(), NotNull::new(OnConflict::Ignore).part_len()?);
1737
1738        str = String::new();
1739        NotNull::new(OnConflict::Replace).part_str(&mut str)?;
1740        assert_eq!(str, "NOT NULL ON CONFLICT REPLACE");
1741        assert_eq!(str.len(), NotNull::new(OnConflict::Replace).part_len()?);
1742
1743        Ok(())
1744    }
1745
1746    #[test]
1747    fn test_unique() -> Result<()> {
1748        let mut str: String;
1749
1750        str = String::new();
1751        Unique::new(OnConflict::Rollback).part_str(&mut str)?;
1752        assert_eq!(str, "UNIQUE ON CONFLICT ROLLBACK");
1753        assert_eq!(str.len(), Unique::new(OnConflict::Rollback).part_len()?);
1754
1755        str = String::new();
1756        Unique::new(OnConflict::Abort).part_str(&mut str)?;
1757        assert_eq!(str, "UNIQUE ON CONFLICT ABORT");
1758        assert_eq!(str.len(), Unique::new(OnConflict::Abort).part_len()?);
1759
1760        str = String::new();
1761        Unique::new(OnConflict::Fail).part_str(&mut str)?;
1762        assert_eq!(str, "UNIQUE ON CONFLICT FAIL");
1763        assert_eq!(str.len(), Unique::new(OnConflict::Fail).part_len()?);
1764
1765        str = String::new();
1766        Unique::new(OnConflict::Ignore).part_str(&mut str)?;
1767        assert_eq!(str, "UNIQUE ON CONFLICT IGNORE");
1768        assert_eq!(str.len(), Unique::new(OnConflict::Ignore).part_len()?);
1769
1770        str = String::new();
1771        Unique::new(OnConflict::Replace).part_str(&mut str)?;
1772        assert_eq!(str, "UNIQUE ON CONFLICT REPLACE");
1773        assert_eq!(str.len(), Unique::new(OnConflict::Replace).part_len()?);
1774
1775        Ok(())
1776    }
1777
1778    #[test]
1779    fn test_primary_key() -> Result<()> {
1780        for so in [Order::Ascending, Order::Descending] {
1781            for conf in [OnConflict::Rollback, OnConflict::Abort, OnConflict::Fail, OnConflict::Ignore, OnConflict::Replace] {
1782                for auto_inc in [true, false] {
1783                    test_sql_part(&PrimaryKey::new(so, conf, auto_inc))?;
1784                }
1785            }
1786        }
1787        Ok(())
1788    }
1789
1790    #[test]
1791    fn test_foreign_key() -> Result<()> {
1792        for defer in [true, false] {
1793            for on_del in [None, Some(FKOnAction::SetNull), Some(FKOnAction::SetDefault), Some(FKOnAction::Cascade), Some(FKOnAction::Restrict), Some(FKOnAction::NoAction)] {
1794                for on_upd in [None, Some(FKOnAction::SetNull), Some(FKOnAction::SetDefault), Some(FKOnAction::Cascade), Some(FKOnAction::Restrict), Some(FKOnAction::NoAction)] {
1795                    // todo: test string params
1796                    assert_eq!(ForeignKey::new("".to_string(), "test".to_string(), on_del, on_upd, defer).part_len(), Err(Error::EmptyForeignTableName));
1797                    assert_eq!(ForeignKey::new("test".to_string(), "".to_string(), on_del, on_upd, defer).part_len(), Err(Error::EmptyForeignColumnName));
1798
1799                    test_sql_part(&ForeignKey::new("test".to_string(), "test".to_string(), on_del, on_upd, defer))?;
1800                }
1801            }
1802        }
1803        Ok(())
1804    }
1805
1806    #[test]
1807    fn test_generated() -> Result<()> {
1808        for gen_as in [None, Some(GeneratedAs::Virtual), Some(GeneratedAs::Stored)] {
1809            // todo: test string params
1810            assert_eq!(Generated::new("".to_string(), gen_as).part_len(), Err(Error::EmptyGeneratorExpr));
1811
1812            test_sql_part(&Generated::new("test".to_string(), gen_as))?;
1813        }
1814
1815        Ok(())
1816    }
1817
1818    #[test]
1819    fn test_column() -> Result<()> {
1820        for typ in [SQLiteType::Blob, SQLiteType::Numeric, SQLiteType::Integer, SQLiteType::Real, SQLiteType::Text] {
1821            for pk in [None, Some(PrimaryKey::default())] {
1822                for uniq in [None, Some(Unique::default())] {
1823                    for fk in [None, Some(ForeignKey::new_default("test".to_string(), "test".to_string()))] {
1824                        for nn in [None, Some(NotNull::default())] {
1825                            for gened in [None, Some(Generated::new_default("expr".to_string()))] {
1826                                assert_eq!(Column::new(typ, "".to_string(), pk.clone(), uniq, fk.clone(), nn, gened.clone()).part_len(), Err(Error::EmptyColumnName));
1827
1828                                let col: Column = Column::new(typ, "test".to_string(), pk.clone(), uniq, fk.clone(), nn, gened);
1829
1830                                if col.pk.is_some() && col.fk.is_some() {
1831                                    assert_eq!(col.part_len(), Err(Error::PrimaryKeyAndForeignKey));
1832                                } else if col.pk.is_some() && col.unique.is_some() {
1833                                    assert_eq!(col.part_len(), Err(Error::PrimaryKeyAndUnique));
1834                                } else {
1835                                    test_sql_part(&col)?;
1836                                }
1837                            }
1838                        }
1839                    }
1840                }
1841            }
1842        }
1843        Ok(())
1844    }
1845
1846    #[test]
1847    fn test_view() -> Result<()> {
1848        'poss: for mut possible in View::possibilities(false).into_iter().map(|boxed| *boxed) {
1849            
1850            for col in &possible.columns {
1851                if col.name.is_empty() {
1852                    assert_eq!(col.part_len(), Err(Error::EmptyColumnName));
1853                    continue 'poss;
1854                }
1855            }
1856            
1857            if possible.name.is_empty() {
1858                assert_eq!(possible.part_len(), Err(Error::EmptyViewName));
1859                continue;
1860            }
1861            if possible.select.is_empty() {
1862                assert_eq!(possible.part_len(), Err(Error::EmptyViewSelect));
1863                continue;
1864            }
1865            
1866            test_sql_part(&possible)?;
1867            test_sql(&mut possible)?
1868        }
1869        Ok(())
1870    }
1871
1872    #[test]
1873    fn test_table() -> Result<()> {
1874        'poss: for mut possible in Table::possibilities(false).into_iter().map(|boxed| *boxed) {
1875            let mut has_pk: bool = false;
1876
1877            for col in &possible.columns {
1878                if col.pk.is_some() && col.unique.is_some() {
1879                    assert_eq!(col.part_len(), Err(Error::PrimaryKeyAndUnique));
1880                    continue 'poss;
1881                }
1882                if col.pk.is_some() && col.fk.is_some() {
1883                    assert_eq!(col.part_len(), Err(Error::PrimaryKeyAndForeignKey));
1884                    continue 'poss;
1885                }
1886                if col.pk.is_some() {
1887                    has_pk = true;
1888                }
1889            }
1890            if !possible.without_rowid && has_pk {
1891                assert_eq!(possible.part_len(), Err(Error::WithoutRowidNoPrimaryKey));
1892                continue;
1893            }
1894
1895            if possible.name.is_empty() {
1896                assert_eq!(possible.part_len(), Err(Error::EmptyTableName));
1897                continue;
1898            }
1899
1900            if possible.columns.is_empty() {
1901                assert_eq!(possible.part_len(), Err(Error::NoColumns));
1902                continue;
1903            }
1904
1905            test_sql_part(&possible)?;
1906            test_sql(&mut possible)?; // FUCK
1907        }
1908        Ok(())
1909    }
1910
1911    #[test]
1912    fn test_schema() -> Result<()> {
1913        {
1914            let mut schema: Schema = Schema::new();
1915            assert_eq!(schema.len(false, false), Err(Error::EmptySchema));
1916        }
1917        for num_tbl in 1..3 {
1918            let mut schema: Schema = Schema::new();
1919            for tbl_idx in 0..num_tbl {
1920                let mut tbl = Table::new_default(format!("table{}", tbl_idx));
1921                tbl = tbl.add_column(Column::new_default("testcol".to_string()));
1922                schema = schema.add_table(tbl);
1923            }
1924            test_sql(&mut schema)?;
1925        }
1926
1927        Ok(())
1928    }
1929
1930    #[cfg(feature = "xml-config")]
1931    mod xml_tests {
1932        use super::*;
1933
1934        #[allow(dead_code)]
1935        impl AnySql {
1936
1937            fn serialized(&self) -> Result<&'static str> {
1938                Ok(match self {
1939                    AnySql::Schema(s) => {Box::leak(quick_xml::se::to_string(s)?.into_boxed_str())}
1940                    AnySql::Table(t) => {Box::leak(quick_xml::se::to_string(t)?.into_boxed_str())}
1941                    AnySql::View(v) => {Box::leak(quick_xml::se::to_string(v)?.into_boxed_str())}
1942                })
1943            }
1944
1945            fn deserialize_schema(xml: &'static str) -> Result<Self> {
1946                Ok(Self::Schema(from_str(xml)?))
1947            }
1948
1949            fn deserialize_table(xml: &'static str) -> Result<Self> {
1950                Ok(Self::Table(from_str(xml)?))
1951            }
1952
1953            fn deserialize_view(xml: &'static str) -> Result<Self> {
1954                Ok(Self::View(from_str(xml)?))
1955            }
1956
1957            fn serialize_deserialize(self) -> Result<&'static str> {
1958                let xml = self.serialized()?;
1959
1960                let deserialized: Self = match self {
1961                    Self::Schema(_) => {Self::deserialize_schema(xml)?},
1962                    Self::Table(_) => {Self::deserialize_table(xml)?},
1963                    Self::View(_) => {Self::deserialize_view(xml)?},
1964                };
1965
1966                assert_eq!(deserialized, self);
1967                Ok(xml)
1968            }
1969
1970            fn deserialize_serialize_inner(self, original_xml: & 'static str) -> Result<Self> {
1971                let new_xml: &'static str = self.serialized()?;
1972                assert_eq!(new_xml, original_xml);
1973                Ok(self)
1974            }
1975
1976            fn deserialize_serialize_schema(xml: &'static str) -> Result<Self> {
1977                Self::deserialize_serialize_inner(Self::deserialize_schema(xml)?, xml)
1978            }
1979
1980            fn deserialize_serialize_table(xml: &'static str) -> Result<Self> {
1981                Self::deserialize_serialize_inner(Self::deserialize_table(xml)?, xml)
1982            }
1983
1984            fn deserialize_serialize_view(xml: &'static str) -> Result<Self> {
1985                Self::deserialize_serialize_inner(Self::deserialize_view(xml)?, xml)
1986            }
1987        }
1988
1989        #[test]
1990        fn test_serialize_deserialize() -> Result<()> {
1991            let tbl = Table::new_default("TestName".to_string()).add_column(Column::new_default("TestCol".to_string()));
1992            let tbl2 = tbl.clone().set_name("TestName2".to_string());
1993            let view = View::new_default("TestView".to_string(), "Select".to_string()).add_column(ViewColumn::new("TestCol".to_string()));
1994            let schema = Schema::new().add_table(tbl.clone()).add_table(tbl2.clone()).add_view(view.clone());
1995            schema.to_any().serialize_deserialize()?;
1996            tbl.to_any().serialize_deserialize()?;
1997            tbl2.to_any().serialize_deserialize()?;
1998            view.to_any().serialize_deserialize()?;
1999            Ok(())
2000        }
2001
2002        #[test]
2003        fn test_deserialize_serialize() -> Result<()> {
2004            let table_xml: &'static str = r#"<table name="test" without_rowid="false" strict="false"><column type="integer" name="test"/></table>"#;
2005            let view_xml: &'static str = r#"<view name="test" temp="false" select="SelectStatement"><column name="test"/></view>"#;
2006            let schema_xml: &'static str = Box::leak(("<schema>".to_string() + table_xml + view_xml + "</schema>").into_boxed_str());
2007            AnySql::deserialize_serialize_table(table_xml)?;
2008            AnySql::deserialize_serialize_view(view_xml)?;
2009            AnySql::deserialize_serialize_schema(schema_xml)?;
2010            Ok(())
2011        }
2012
2013        #[test]
2014        fn some_test() -> Result<()> {
2015            let raw: &str = r#"
2016<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
2017<schema xmlns="https://crates.io/crates/sqlayout">
2018
2019  <!-- Card data -->
2020  <table name="updates" strict="true">
2021    <column name="ID" type="integer">
2022      <pk/>
2023      <not_null/>
2024    </column>
2025    <column name="timestamp" type="integer">
2026      <not_null/>
2027    </column>
2028    <column name="guid" type="text">
2029      <not_null/>
2030      <unique/>
2031    </column>
2032  </table>
2033
2034  <table name="migrations" strict="true">
2035    <column name="ID" type="integer">
2036      <pk/>
2037      <not_null/>
2038    </column>
2039    <column name="timestamp" type="integer">
2040      <not_null/>
2041    </column>
2042    <column name="GUID" type="text">
2043      <not_null/>
2044      <unique/>
2045    </column>
2046  </table>
2047
2048  <table name="card_data" strict="true">
2049    <column name="ID" type="integer">
2050      <pk/>
2051      <not_null/>
2052    </column>
2053  </table>
2054
2055  <!-- Collection Data -->
2056  <table name="card_location" strict="true">
2057    <column name="ID" type="integer">
2058      <pk/>
2059      <not_null/>
2060    </column>
2061    <column name="name" type="text">
2062      <not_null/>
2063    </column>
2064    <column name="description" type="text"/>
2065  </table>
2066
2067  <table name="card_collection" strict="true">
2068    <column name="ID" type="integer">
2069      <pk/>
2070      <not_null/>
2071    </column>
2072    <column name="card_ID" type="integer">
2073      <fk foreign_table="card_data" foreign_column="ID"/>
2074      <not_null/>
2075    </column>
2076    <column name="count" type="integer">
2077      <not_null/>
2078    </column>
2079    <column name="finish" type="integer">
2080      <!-- enum -->
2081      <not_null/>
2082    </column>
2083    <column name="condition" type="integer">
2084      <!-- enum -->
2085    </column>
2086    <column name="location" type="integer">
2087      <fk foreign_table="card_location" foreign_column="ID"/>
2088      <not_null/>
2089    </column>
2090    <column name="location_page" type="integer"/>
2091  </table>
2092</schema>
2093"#;
2094            let _: Schema = quick_xml::de::from_str(raw)?;
2095            Ok(())
2096        }
2097
2098        #[test]
2099        fn xmlns_test() -> Result<()> {
2100            let tbl: Table = Table::new_default("test".to_string()).add_column(Column::new_default("testcol".to_string()));
2101            let sch: Schema = Schema::new().add_table(tbl.clone());
2102
2103            let xml: String = quick_xml::se::to_string(&sch)?;
2104            println!("Schema XML:\n{}", xml);
2105            let xml: String = quick_xml::se::to_string(&tbl)?;
2106            println!("Table XML:\n{}", xml);
2107            Ok(())
2108        }
2109    }
2110
2111    #[cfg(feature = "rusqlite")]
2112    mod rusqlite {
2113        // todo
2114    }
2115}