1mod 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#[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
45trait SQLPart {
50 fn part_len(&self) -> Result<usize>;
51
52 fn part_str(&self, sql: &mut String) -> Result<()>;
53
54 #[cfg(test)]
58 fn possibilities(illegal_variants: bool) -> Vec<Box<Self>>;
59}
60
61pub trait SQLStatement {
64 fn len(&mut self, transaction: bool, if_exists: bool) -> Result<usize>;
68
69 fn build(&mut self, transaction: bool, if_exists: bool) -> Result<String>;
76
77 #[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 #[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#[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 Blob,
114 Numeric,
115 Integer,
116 Real,
117 Text,
118}
119
120impl Default for SQLiteType {
121 fn default() -> Self {
122 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#[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#[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 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#[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 Self::NoAction
277 }
278}
279
280impl SQLPart for FKOnAction {
281 fn part_len(&self) -> Result<usize> {
282 Ok(match self {
283 FKOnAction::SetNull => { 8 } FKOnAction::SetDefault => { 11 } FKOnAction::Cascade => { 7 }
286 FKOnAction::Restrict => { 8 }
287 FKOnAction::NoAction => { 9 } })
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#[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#[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, }
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#[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#[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#[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#[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#[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#[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#[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 + self.temp as usize * 10 + 5 + self.if_exists as usize * 14 + self.name.len()
1036 + 2; let post_coll: usize = 5 + 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; cnt += coll.part_len()?;
1049 }
1050 cnt - 2 };
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 }
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#[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 + self.if_exists as usize * 14 + self.name.len()
1252 + 2 + cols_len
1254 + self.columns.len() - 1 + 1 + self.without_rowid as usize * 14 + ((self.without_rowid && self.strict) as usize) + self.strict as usize * 7 )
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 }
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#[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()); 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#[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 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 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 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)?; }
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 }
2115}